How do I use Sinon with Typescript?

You may need to use an <any> type assertion to make the type wide before you narrow it to your specific type:

var myServiceMock: MyStuff.MyService = 
    <MyStuff.MyService> <any> (sinon.mock(MyStuff.MyService));

Just to clarify one behaviour of sinon - although you pass in MyStuff.MyService, whatever you pass to the mock method is only used to provide better error messages.

If you want the mock to have methods and properties, you need to add them.

If you want automatically created fakes, you can grab the FakeFactory from tsUnit, which creates a fake version with some default values that you can opt to override - in JavaScript this is pretty easy stuff (plus by not using too much mock functionality, you can ensure you are testing behaviour rather than implementation).

Example use of FakeFactory:

var target = tsUnit.FakeFactory.getFake<RealClass>(RealClass);
var result = target.run();
this.areIdentical(undefined, result);

Use ts-sinon.

It lets you:

  • stub objects
  • stub interfaces

Sinon can create a stub based on a constructor quite easily if, instead of mock, you use the createStubInstance method.

An example using mocha, chai, sinon and sinon-chai, could look like this:

import * as sinon from 'sinon';
import * as chai from 'chai';

// ... imports for the classes under test

const expect    = chai.expect;
const sinonChai = require("sinon-chai");

chai.use(sinonChai);

describe('MyController', () => {
    it('uses MyService', () => {

        let myService  = sinon.createStubInstance(MyStuff.MyService),
            controller = new MyStuff.MyController(myService as any, ...);

        // ... perform an action on the controller 
        // that calls myService.aMethodWeAreInterestedIn

        // verify if the method you're interested in has been called if you want to
        expect(myService.aMethodWeAreInterestedIn).to.have.been.called;
    });
});

I've published an article, which you might find useful if you'd like to learn more about the different test doubles and how to use them with Sinon.js.

Hope this helps!

Jan


In Typescript this can be achieved by using sinon.createStubInstance and SinonStubbedInstance class.

Example:

let documentRepository: SinonStubbedInstance<DocumentRepository>;

documentRepository = sinon.createStubInstance(DocumentRepository);

Now you have a full intellisense for working with all stubbed methods of this class.

Example Arrange:

documentRepository.delete.resolves({deletedCount: 1});

documentRepository.update.throws(error);

Example Assert:

sinon.assert.calledOnce(documentRepository.update);

There is only one place where you would need to perform type casting and that is the initiallization of the class you want to unit test.

Example:

documentsController =
  new DocumentsController(
    userContext,
    documentRepository as unknown as DocumentRepository);

Hope this will help. More on this article.