How to assert certain method is called with Ruby minitest framework?

25,342

Solution 1

With minitest you use expect method to set the expectation for a method to be called on a mock object like so

obj = MiniTest::Mock.new
obj.expect :right

If you want to set expectation with parameters and return values then:

obj.expect :right, return_value, parameters

And for the concrete object like so:

obj = SomeClass.new
assert_send([obj, :right, *parameters])

Solution 2

Minitest has a special .expect :call for checking if some method is called.

describe SomeClass do
  it "should invoke right function" do
    mocked_method = MiniTest::Mock.new
    mocked_method.expect :call, return_value, []
    some_instance = SomeClass.new
    some_instance.stub :right, mocked_method do
      some_instance.invoke_function("right")
    end
    mocked_method.verify
  end
end

Unfortunately this feature is not documented very well. I found about it from here: https://github.com/seattlerb/minitest/issues/216

Solution 3

According to the given example, there is no other delegate class, and you want to make sure the method is called properly from the same class. Then below code snippet should work:

class SomeTest < Minitest::Test
  def setup
    @obj = SomeClass.new
  end

  def test_right_method_is_called
    @obj.stub :right, true do
      @obj.stub :wrong, false do
        assert(@obj.invoke_function('right'))
      end
    end
  end

  def test_wrong_method_is_called
    @obj.stub :right, false do
      @obj.stub :wrong, true do
        assert(@obj.invoke_function('other'))
      end
    end
  end
end

The idea is to stub [method_expect_to_be_called] by returning a simple true value, and in the stub block assert it's indeed being called and returning the true value. To stub the other unexpected method is just to make sure that it's not being called.

Note: assert_send won't work correctly. Please refer to official doc.

In fact, below statement will pass, but doesn't mean it's working as expected:

assert_send([obj, :invoke_function, 'right'])
# it's just calling invoke_function method, but not verifying any method is being called
Share:
25,342
steveyang
Author by

steveyang

After my passion for creation, I learned programming-stuff myself since the year of 2011 and now I am comfortable with html5,css3 and javaScript. I also love the simply design of linux and cleanliness of python and ruby. I am working as the leading UI designer and frontend developer at ELE.ME

Updated on January 18, 2022

Comments

  • steveyang
    steveyang over 2 years

    I want to test whether a function invokes other functions properly with minitest Ruby, but I cannot find a proper assert to test from the doc.

    The source code
    class SomeClass
      def invoke_function(name)
        name == "right" ? right () : wrong ()
      end
    
      def right
        #...
      end
    
      def wrong
        #...
      end
    end
    
    The test code:
    describe SomeClass do
      it "should invoke right function" do
        # assert right() is called
      end
    
      it "should invoke other function" do
        # assert wrong() is called
      end
    end