Question

I have a test block:

describe 'without' do

  describe 'author' do
    let(:author)  {nil}
    it('fails')   {assert_raises(ArgumentError) { excerpt }}
  end

  describe 'title' do
    # same content as above, but testing title
  end

  describe 'content' do
    # same content as above, but testing content
  end

end

This works fine and the tests pass - but since there's a lot of repetition here, I wanted to refactor:

describe 'without' do

  describe 'author' do
    let(:author)  {nil}
    it('fails')   {assert_failure(excerpt} # added a method in this line
  end

  describe 'title' do
    # same content as above, but testing title
  end

  describe 'content' do
    # same content as above, but testing content
  end

  # and the method here
  def assert_failure(instance)
    assert_raises(ArgumentError) { instance }
  end

end

However this doesn't work - my tests fail with the following error:

construction::without::author#test_0001_fails:
ArgumentError: Excerpt cannot be built: Author missing

Which is the error that I would expect to be raised with missing information - and is exactly what I'm testing. So it seems that when this assertion is extracted, the ArgumentError is being raised and stopping the test before assert_raises can make any kind of comparison. I looked into the code for this assertion, but I can't make out why this would happen when the code is extracted into another method, but not when it's in-line.

Was it helpful?

Solution

When you write with the following syntax:

assert_raises(ArgumentError) { excerpt }

What you are actually passing to assert_raises is a block. This means that the code (excerpt) is not evaluated until the method itself decides it wants to evaluate it.

With this syntax, though:

assert_failure(excerpt)

excerpt is evaluated before assert_failure starts.

If you want to duplicate the above behavior, you need to pass assert_failure a block:

def assert_failure(&block)
  assert_raises(ArgumentError, &block)
end

  describe 'author' do
    let(:author)  {nil}
    it('fails')   { assert_failure { excerpt } }
  end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top