From 63efd01c3fb59bdbadaec9ba724ff39523364545 Mon Sep 17 00:00:00 2001 From: biniam Date: Mon, 13 May 2019 11:42:20 -0400 Subject: [PATCH] docs: add stub service section --- docs/site/Testing-your-application.md | 61 ++++++++++++++++++- .../unit/controllers/todo.controller.unit.ts | 1 + 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/docs/site/Testing-your-application.md b/docs/site/Testing-your-application.md index 7027a1236bbc..a0c659b795ed 100644 --- a/docs/site/Testing-your-application.md +++ b/docs/site/Testing-your-application.md @@ -408,7 +408,7 @@ Verify how was the stubbed method executed at the end of your unit test (in the ```ts // expect that repository.find() was called with the first // argument deeply-equal to the provided object -sinon.assert.calledWithMatch({where: {id: 1}}); +sinon.assert.calledWithMatch(findStub, {where: {id: 1}}); ``` See [Unit test your controllers](#unit-test-your-controllers) for a full @@ -416,9 +416,64 @@ example. #### Create a stub Service -{% include content/tbd.html %} +If your controller relies on service proxy for service oriented backends such as +REST APIs, SOAP Web Services, or gRPC microservices, then we can create stubs +for the service akin to the steps outlined in the above +[stub repository](#create-a-stub-repository) section. Consider a dependency on a +`GeoCoder` service that relies on a remote REST API for returning coordinates +for a specific address. -The initial beta release does not include Services as a first-class feature. +```ts +export interface GeocoderService { + geocode(address: string): Promise; +} +``` + +The first step is to create a mocked instance of the `GeocoderService` API and +configure its `geocode` method as a Sinon stub: + +```ts +describe('GeocoderController', () => { + let geoService: GeoCoderService; + let geocode: sinon.SinonStub; + + beforeEach(givenMockGeoCoderService); + + // your unit tests + + function givenMockGeoCoderService() { + // this creates a stub with GeocoderService API + // in a way that allows the compiler to verify type correctness + geoService = {geocode: sinon.stub()}; + + // this creates a reference to the stubbed "geocode" method + // because "geoService.geocode" has type from GeocoderService + // and does not provide Sinon APIs + geocode = geoService.geocode as sinon.SinonStub; + } +}); +``` + +Afterwards, we can configure the `geocode` stub's behaviour before the `act` +phase of our test(s): + +```ts +// geoService.geocode() will return a promise that +// will be resolved with the provided array +geocode.resolves([{y: 41.109653, x: -73.72467}]); +``` + +Lastly, we'll verify how the stub was executed: + +```ts +// expect that geoService.geocode() was called with the first +// argument equal to the provided address string +sinon.assert.calledWithMatch(geocode, '1 New Orchard Road, Armonk, 10504'); +``` + +Check out +[TodoController unit tests](https://github.com/strongloop/loopback-next/blob/bd0c45033503f631a533ad6176620354d9cf6768/examples/todo/src/__tests__/unit/controllers/todo.controller.unit.ts#L53-L71) +illustrating the above points in action for more information. ### Unit test your Controllers diff --git a/examples/todo/src/__tests__/unit/controllers/todo.controller.unit.ts b/examples/todo/src/__tests__/unit/controllers/todo.controller.unit.ts index 582ec2d21c25..b8e3d07c53ef 100644 --- a/examples/todo/src/__tests__/unit/controllers/todo.controller.unit.ts +++ b/examples/todo/src/__tests__/unit/controllers/todo.controller.unit.ts @@ -67,6 +67,7 @@ describe('TodoController', () => { expect(result).to.eql(expected); sinon.assert.calledWith(create, input); + sinon.assert.calledWith(geocode, input.remindAtAddress); }); });