- Identify dependencies to be controlled when testing production code
- Install a stub library & get access to it in your test code
- Learn how to stub a method on a dependency and control its return value
- Write a passing test using a stubbed dependency
- Refactor repetatives tasks out into test set-up (
beforeEach
) and tear-down (afterEach
) hooks - Read up on how Angular handles dependency management and how you might control dependencies in this environment. This is much more similar to how static languages such as C# and Java manage dependencies.
Same pattern as previous pracs
- Commit any outstanding changes on your Prac03 branch:
git commit -am 'Some message'
- Head back over to master:
git checkout master
- Check out the Start Point for Prac 4:
git checkout Prac04-StartPoint
- Create a branch to make your changes on without impacting the main repo:
git checkout -b Prac04
- Install Sinon and add it as a dev dependency for our project
- We need to write some tests for
pet-service.js
. Identify the dependency to be stubbed. - Create a new test file for
pet-service.js
- Get a reference to the code we're testing
- Get references to Sinon and HttpClient
- Add a describe block for PetService
- Nest a describe block for getting pet information
- Add an it block for testing the transformation of the JSON result
- Find out what the JSON result from the external API is going to look like
- Create a mock return result for test purposes
- Instruct sinon to stub the
get
method onhttpClient
, and resolve its promise with our fake result - Call the service and assert on the result
- Instruct sinon to release the stub and restore the original functionality
- Run the test and see a fast, green result
- Ensure that the actual
httpClient.get
method isn't being called
Here's a step-by-step walkthrough of the practical steps, for if you get stuck :)
- Install Sinon and add it as a dev dependency for our project
npm install sinon --save-dev
- We need to write some tests for
pet-service.js
. Identify the dependency to be stubbed.- At the top of
pet-service.js
, it requireshttp-client.js
pet-service
useshttp-client
makes a call off to an external API- To test that quickly and reliably we need to stub the
http-client
- At the top of
- Create a new test file for
pet-service.js
- Create a new file
test\pet-service-tests.js
- Create a new file
- Get a reference to the code we're testing
var petService = require('../src/pet-service');
- Get references to Sinon and HttpClient
var sinon = require('sinon');
var httpClient = require('../src/http-client');
- Add a describe block for PetService
describe('PetService', function() { ... });
- Nest a describe block for getting pet information
describe('when retrieving pet details', function() { ... });
- Add an it block for testing the transformation of the JSON result
it('returns a nicely consumable JSON result', function() { ... });
- Find out what the JSON result from the external API is going to look like
- Get
https://juniordev-refactor.azurewebsites.net/api/Pets?petName=Beaglier
- Inspect the structure of the JSON result
- Get
- Create a mock return result for test purposes
var externalApiJsonResult = { "AnimalVariety": "Dog", "AnimalInformation": "Beagliers are beautiful", "ReferenceSource": "https://en.wikipedia.org/wiki/Beaglier", "Base64EncodedVisualDepiction": "base64dog" };
- Instruct sinon to stub the
get
method onhttpClient
, and resolve its promise with our fake resultsinon.stub(httpClient, 'get');
httpClient.get.resolves(externalApiJsonResult);
- Call the service and assert on the result
return petService.getPetDetails("Beaglier") .then(result => { result.should.have.property("info").which.equals("Beagliers are beautiful"); result.should.have.property("source").which.equals("https://en.wikipedia.org/wiki/Beaglier"); result.should.have.property("image").which.equals("base64dog"); });
- Instruct sinon to release the stub and restore the original functionality
httpClient.get.restore();
- Run the test and see a fast, green result
- Ensure that the actual
httpClient.get
method isn't being called- You could set a breakpoint in the actual
get
method and debug, or add aconsole.log
entry to the actualget
method to ensure nothing is logged in the console during the test run
- You could set a breakpoint in the actual