Upgrade to Pro — share decks privately, control downloads, hide ads and more …

I know everything about mocks, stubs, and spies in RSpec

I know everything about mocks, stubs, and spies in RSpec

The slide deck is for English Tech LT#2.

https://andpad.connpass.com/event/231653/

Hideaki ishii

December 24, 2021
Tweet

More Decks by Hideaki ishii

Other Decks in Programming

Transcript

  1. I know everything about mocks, stubs, and spies in RSpec

    @danimal141 2021/12/23 English Tech LT#2
  2. Introduction ID: @danimal141 Name: Hideaki Ishii Work as a software

    engineer for about 10 years. I like Ruby, Golang, TypeScript. Lately, I use GraphQL (graphql-ruby).
  3. See difference between about mocks, stubs, and spies using rspec-mocks!

  4. Japanese kanzen rikai!

  5. Let’s think with some examples…

  6. Stubs

  7. There is some API client wrapper. class SomeClient def request

    body = some_lib.request JSON.parse body end private def some_lib @some_lib ||= SomeLib.new end end
  8. Test with stubs. describe 'SomeClient#request' before do allow(client).to receive(:some_lib).with(no_args).and_return(some_lib) #

    Stub some_lib's behavior and can avoid requesting actually. allow(some_lib).to receive(:request).with(no_args).and_return(expected_boby) end let(:client) { SomeClient.new } # instance_double: # - Can stub methods. # - If you try to stub the undefined method, it would raise an error. let(:some_lib) { instance_double(SomeLib) } let(:expected_body) { ... } let(:expected_json) { JSON.parse expected_body } subject { client.request } # call the subject. it { is_expected.to eq expected_json } end
  9. Mocks

  10. Test with mocks. describe 'SomeClient#request' before { allow(client).to receive(:some_lib).with(no_args).and_return(some_lib) }

    let(:client) { SomeClient.new } let(:some_lib) { instance_double(SomeLib) } let(:expected_body) { ... } let(:expected_json) { JSON.parse expected_body } subject { client.request } it do # ensure whether it's really called once expectedly. # set message expectations # call the expectation first. expect(some_lib).to receive(:request).with(no_args).and_return(expected_boby).once # call the subject. is_expected.to eq expected_json end
  11. Spies

  12. In rspec-mocks/v/3-6/docs/basics/spies, Spies are described as follows: Spies are an

    alternate type of test double that support this pattern by allowing you to expect that a message has been received after the fact, using have_received.
  13. Test with spies. describe 'SomeClient#request' before { allow(client).to receive(:some_lib).with(no_args).and_return(some_lib) }

    let(:client) { SomeClient.new } let(:some_lib) { instance_double(SomeLib) } let(:expected_body) { ... } let(:expected_json) { JSON.parse expected_body } subject { client.request } it do # call the subject first. is_expected.to eq expected_json # set message expectations # call the expectation after calling the subject. expect(some_lib).to have_received(:request).with(no_args).and_return(expected_boby).once end end
  14. Conclusion stub Provides hard-coded values for method calls. mock mock

    is similar to stub, but represents the specification of the call at tests. set message expectation -> test spy test -> verify message expectation Can write tests more naturally.
  15. Thanks!