Isolating with spies ;TLDR
Read ⚡️ Stubs first.
A spy or a mock is a function that records the interactions our application has with it. In Jest, a mock function becomes a spy when we use a toHaveBeenCalled or toHaveBeenCalledWith matcher.
.toHaveBeenCalled() - expect a mock function to have been called as part of the test.
.toHaveBeenCalledWith(arg1, arg2) - expect a mock function to have been called with one or more arguments as part of the test.
Let's look at an example:
In the above example, assume that our test is part of the test suite for VendingMachine. We don't want to pass a real Snack object into our VendingMachine's purchaseSnack method, as this wouldn't be an isolated test, so instead we stub snack, ensuring the interface matches that of our Snack prototype/constructor. When our stub does get passed into purchaseSnack, the addSale method gets called, which in this case is our spy. The assertion below expect(snack.addSale).toBeCalled() therefore passes, as the addSale method was called.
Challenge
We have a problem in our Ship test suite currently in that 3 tests directly test the Port object:
Refactor these tests so that they incorporate spies.
To complete this challenge, you will need to:
Note many of the changes below will happen in the beforeEach function callback. You will need to use the matcher toHaveBeenCalledWith.
- In
can set sailyou will need to remove the assertion onport.shipsand instead assert thatship.setSailcallsport.removeShip(whereportis a stub, andremoveShipis a method on that stub). - In
gets added to port on instantiationyou will need to remove the assertion onport.shipsand instead assert thatport.addShiphas been called (again,addShipwill be a spy on aportstub). - In
can dock at a different portyou will need to remove the assertion oncalais.shipsand instead assert thatcalais.addShiphas been called withship(again,addShipwill be a spy on aportstub).