How to assert block of a mock in mocha

2.4k views Asked by At

This example is contrived, please don't take it verbatim as my code.

I have the need to assert something like the following:

def mymethod
    Dir.chdir('/tmp') do
        `ls`
    end
end

In the end I want to assert that:

  1. Dir.chdir is invoked with the appropriate parameters.
  2. ` is invoked with the appropriate parameters

I started off with...

Dir.expects(:chdir).with('/tmp')

but after that I'm not sure how to invoke the block passed to Dir.chdir.

1

There are 1 answers

0
Rich Drummond On BEST ANSWER

You need to use the mocha yields method. Also, writing an expectation for the backtick method is rather interesting. You need to make an expectation like this:

expects("`")

But on what object? You might think on Kernel or Object, but that doesn't actually work.

As an example, given this module:

module MyMethod
  def self.mymethod
    Dir.chdir('/tmp') do
      `ls`
    end
  end
end

I could write a test like this:

class MyMethodTest < Test::Unit::TestCase
  def test_my_method
    mock_block = mock
    mock_directory_contents = mock
    MyMethod.expects("`").with('ls').returns(mock_directory_contents)
    Dir.expects(:chdir).yields(mock_block).returns(mock_directory_contents)
    assert_equal mock_directory_contents, MyMethod.mymethod
  end
end

Part of the trick is to figure out which object to expect the backtick method to be invoked on. It depends on the context - whatever self is when that method is invoked. Here it is the module MyMethod, but depending on where you define mymethod it will be different.