Slide 1

Slide 1 text

Stub & Mock 03.2023

Slide 2

Slide 2 text

TestDouble (1/1) Stuby i Mocki are TestDoubles Fundamental part of TDD, one of BetterSpecs directives mentioned couple times, impotant in Martina Fowler’s articles about tests

Slide 3

Slide 3 text

Mock (2/1) Mock in RSpec usually looks like: expect(some_object).to receive(some_method).and_return(some_value) If some_object does not receive some_method then the test fails. Same if it does not return some_value. We could add receive(some_method).with(arg: ugment) to be more precise with what we expect from our mock. Other testing framework albo have build in mocks, like MiniTest stuff = MiniTest::Mock.new stuff.expect :thing?, true service = MyService.new(stuff) service.call stuff.verify If MyService calls thing? on stuff tests succeeds. If it does not call, then it fails.

Slide 4

Slide 4 text

Stub (3/1) Simple Stub w RSpec is usually: allow(some_object).to receive(some_method).and_return(some_value) Time.stub :now, Time.new(2023, 03, 07).utc do MyObject.new.are_we_there_yet? end MiniTest, closer to pure ruby’ego we can for example: Method now is stubbed on Time object and durin the testing of MyObject we will always get now with the same value (when we call are_we_there_yet? whic calls Time.now we will get the value of Time.new(2023, 03, 07).utc)

Slide 5

Slide 5 text

Mock vs Stub (4/1) Summary of the difference expect(some_object).to receive(some_method).and_return(some_value) allow(some_object).to receive(some_method).and_return(some_value) Mock: Stub: Monitors the object as instructed, throws an error if the expectations are not met. It can replace a value for what it monitors. Mainly used to double objects, when we mostly care about the output, although checking the input can also be a part of the mock. Replaces an object or its part as instructed. Bends the behaviour of the stubbed object for the needs of the test. Mostly used to double an object, where me mostly care about the input, due to behaviour modifications. Output is also important, but it is tested on a stub.

Slide 6

Slide 6 text

Mock & Stub (5/1) We can join them together, giving us simplified and faster test structures: Mock that returns a stub (RSpec) mock_object = MiniTest::Mock.new mock_object.expect :list_all, [] Client::Request.stub :new, mock_client do # do something using the mocked object end The same idea, mock returns a stub (MiniTest)

Slide 7

Slide 7 text

Stub Pure Ruby (5/1) company = Company.create(name: "2N") def company.active?; true; end def company.add_employee(*args); raise PolicyError::NotAuthorized; end If we do: company2 = Company.create(name: ‘Black Mesa’) then the values won’t get stubbed. On company variable they will stay stubbed