Quantcast
Channel: Notes to self
Viewing all articles
Browse latest Browse all 51

Introduction to Minitest Mocks

$
0
0

Test doubles likes mocks and stubs can help us with isolating code under test with the rest of the system. Here’s how to mock in Minitest.

Mocks

Mocks are usually small handcrafted objects that are ready to be passed to methods under test to invoke a specific scenario we want to see in the test.

Let’s imagine a small code example:

classStripeProviderdefcharge# code to charge customerendendclassPaymentdefinitialize(provider: StripeProvider.new)@provider=providerenddefcharge(user,amount)@provider.charge(user,amount)endend

Now if we would pass a real gateway object in the test, we would have to set up a test environment on the provider side and depend on an HTTP call. Instead we can create a mock payment provider for the test case:

require"minitest/autorun"classPaymentTest<Minitest::Testdefsetup@mock_provider=Minitest::Mock.new@mock_provider.expect(:charge)do|user,amount|trueendenddeftest_user_is_chargedpayment=Payment.new(provider: @mock_provider)assertpayment.charge(User.new,100)assert_mock@mock_providerendend

Here we passed a mocked provider and the code for the Payment object stayed the same.

Minitest implements mocks in Minitest::Mock which lets us define expectations for called methods with expect and then verify them with assert_mock or verify. This method confirms the method was actually called.

Since Mocks needs to be passed directly this way in test, they are often used together with stubs. Let’s do one more example, this time we’ll use a stub to return a mock provider automatically:

# test/models/payment_test.rbrequire"test_helper"classPaymentTest<ActiveSupport::TestCasesetupdo@mock_provider=Minitest::Mock.newdef@mock_provider.charge(user,amount);true;endendtest"#charge"doStripeProvider.stub:new,@mock_providerdopayment=Payment.newassertpayment.charge(User.new,100)endendend

As you can see the default StripeProvider was replaced with our mock. This is a useful technique when passing the mocked object directly is not possible.

Also, we defined charge without any expectations. We can add methods on the mock object like this with just Ruby when we don’t need to check if they were run.


Viewing all articles
Browse latest Browse all 51

Trending Articles