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).
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.