Let's focus on test/controllers/messages_controller_test.rb
now.
bin/rails t test/controllers/messages_controller_test.rb
This outputs a lot of NameErrors like this:
NameError: undefined local variable or method `new_message_url' for #<MessagesControllerTest:0x00007fb6bcbf85e0 @_routes=nil, @NAME="test_shoul....
Remember how we nested our messages under channels, we need to update the urls to reflect this.
Change all the message_path
calls to channel_message_path
calls, message_url
calls to channel_message_url
calls, new_message_url
calls to new_channel_message_url
calls, etc.
We also need to add a channel to the urls. So channel_message_path(@message)
would become channel_message_path(@channel, @message)
.
We can get @channel in the setup method by adding @channel = @message.recipient
after the @message initialization.
Let's run our the tests again.
Now we see errors that look like this:
MessagesControllerTest#test_should_show_message:
NameError: uninitialized constant Recipient
test/controllers/messages_controller_test.rb:8:in `block in <class:MessagesControllerTest>'
This took me a moment to realize, however our fixtures file test/fixtures/messages.yml
has set all the recipient_type to Recipient
s, which doesn't exist. Remove the recipient_type
rows and add suffix the recipient
line with (Channel)
which hints to Rails that we want to use a channel.
Remember that we disabled a lot of the messages routes? We need to reflect that in the tests, otherwise we'll get a No route matches
errors.
Delete everything except the create, update, and destroy tests.
We changed a few things in our messages controller:
- We only respond to JSON requests
- We don't allow recipient or sender to be passed in
Let's accommodate those!
We don't redirect anymore, so let's remove those assert_redirected_to
calls and replace them with assert_response :success
calls (or assert_response :created
for the create action).
Change params to include only content. Both create and update should have params: { message: { content: "content" } }
Let's make sure things are assigned properly as well. In create's test add:
message = Message.last
assert_equal @channel, message.recipient
assert_equal @message.sender, message.sender
In update's test add:
assert_equal @channel, @message.reload.recipient
assert_equal @message.sender, message.reload.sender
.reload is necessary because we changed the message and we must tell Rails to reload it all.
Tests should now pass for everything!
- Update the URLs to reflect that we nested messages under channels
- Remove
recipient_type
lines fromtest/fixtures/messages.yml
- Add
(Channel)
suffices to recipient lines intest/fixtures/messages.yml
- In
test/controllers/messages_controller_test.rb
, delete everything except the create, update, and destroy tests. - In
test/controllers/messages_controller_test.rb
, addparams: { message: { content: "content" } }
to create and update tests, removing the existing params - In
test/controllers/messages_controller_test.rb
, removeassert_redirected_to
calls and replace them withassert_response :success
calls (orassert_response :created
for the create action). - Add this after the create POST action in the create test:
message = Message.last assert_equal @channel, message.recipient assert_equal @message.sender, message.sender
- In update's test add:
assert_equal @channel, @message.reload.recipient assert_equal @message.sender, message.reload.sender
- All tests now pass!
https://github.com/dcsil/rails-tutorial-example/commit/55531e954be32c9ba2701f920bb3ae8081ddd213