Search code examples
ruby-on-railsruby-on-rails-3tdd

Rails functional tests- nesting assertion within assert_raises?


I've got a functional test like the following:

test "vendors can't create notes for products they don't own" do
  login vendor
  params = { format: 'json', note: { content: "shouldn't exist" }, vendor_id: other_product.vendor.id }

  assert_raises(CanCan::AccessDenied) do
    assert_no_difference "Note.count" do
      post :create, params
    end
  end
end

When run, this test passes, but the output shows only 1 assertion:

1 tests, 1 assertions, 0 failures, 1 errors, 0 skips

Does these nested assert_no_difference assertion even get run, since the AccessDenied exception was raised?

If I run them as two separate assertions, like this:

assert_raises(CanCan::AccessDenied) do
  post :create, params
end

assert_no_difference "Note.count" do
  post :create, params
end

... the test errors out with CanCan::AccessDenied: You are not authorized to access this page. So, does the nested assertion in the first example actually get run? I know it's somewhat redundant, but it's only a couple of extra lines of code and offers some additional peace of mind (but only if it's actually doing anything).


Solution

  • No, your assert_no_difference assertion is not run, as you noticed. Raising an exception breaks out of the block completely.

    The solution is to reverse the nesting order of your assertions, like so:

    assert_no_difference "Note.count" do
      assert_raises(CanCan::AccessDenied) do
        post :create, params
      end
    end
    

    The assert_raises call catches the exception, allowing execution to continue, so the outer block completes and the Note.count check is performed.