Testing Controller Instance Variables Using the Assigns Method

Daniel Pericich
3 min readSep 23, 2021
Photo by Roberto Nickson on Unsplash

Testing endpoints in Ruby on Rails can be either very simple, or incredibly frustrating. If you are performing a simple get statement for a JSON object, setting up tests that return this object for assertions is easy. However, how do you test an endpoint that returns a number of instance variables for use in ERB files?

A tenant of good OOP programming is keeping a clear division between public and private interface. Other models, controllers and views should be able to access only what they need to. By keeping the surface areas of your interface small, you avoid code misuse or breaking changes as a project develops. To stay true to this, of this we don’t want to expose variables just to test more easily. This is where the assigns method comes in.

What is Assigns?

Using a test gem like RSpec allows you to make use of shortcut variables like “payload.” When you make a request to an endpoint in an “it” statement, the response object is stored in this payload. This is great for easy access to the return object, but does not allow you to interact with instance variables. This is where assigns comes in.

Assigns is a method that takes any instance variables in your controller endpoint and stores them in a hash where the keys are the variable names. From this you can access and manipulate the variable values to make more robust assertions.

Where does assigns come from though? I had to do some digging to determine if assigns was a Ruby, Ruby on Rails or Rspec method. After some digging I found that it is a method from Ruby on Rails, specific to ActionController. Having it as a Rails method allows anyone to use it, whether or not they are writing tests using RSpec.

How to Use Assigns

Assigns is not an overly difficult method to use, so our example will be very simple. Say that we want to test the contents of a submission template we are sending. We may have a page that will inform a user that their order was successful after going through a checkout process. Let’s call this method “confirm_payment”. Here we can see what our response is for confirm_payment:

Figure 1. confirm_payment endpoint with instance variables

We will be using the confirm_payment.html.erb file for our view format so our instance variables will be available for populating our html. But how are we going to test this? If we run the following assertion, we get back a payload of nothing:

Figure 2. Accessing empty object using payload

These instance variables are not available as a payload response because confirm_payment.html.erb is rendered server side, so they are not available for use or manipulation by the client. To access our variables, we will need to grab the values outside of the payload. This is where assigns comes in handy.

Instead of trying to test our instance variables from the payload, we will extract and assign our values to variables within the assertion using assigns. The following is the correct way to test our customer_name value:

Figure 3. Using assigns to access instance variable in our test

With that we are able to access not only our customer_name instance variable, but the items_purchased and expected_delivery_date variables as well. We are now able to properly test our endpoint.

Conclusion

Testing can be frustrating without the right tools. I hope that you feel confident in your understanding and ability to use assigns to fully test your controller methods’ instance variables and write clean, well covered code. Let me know in the comments if you found this helpful!

Notes

https://apidock.com/rails/ActionController/TestProcess/assigns

http://joshfrankel.me/blog/accessing-instance-variables-within-a-rspec-controller-test/

--

--

Daniel Pericich

Former Big Beer Engineer turned Full Stack Software Engineer