Как использовать Sinon с Typescript?

Если я использую sinon с typescript, то как мне приложить синон-макет к экземпляру моего объекта?

Например, SinonMock будет возвращен, но мой тестируемый контроллер может потребовать передачи определенного конструктора в его конструктор.

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

controllerUnderTest = new MyStuff.MyController(myServiceMock, $log);

Можно использовать синон с Typescript?

Ответ 1

Возможно, вам придется использовать утверждение типа <any>, чтобы сделать тип широким, прежде чем сузить его до вашего конкретного типа:

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

Просто, чтобы прояснить одно поведение синона - хотя вы проходите в MyStuff.MyService, все, что вы передаете методу mock, используется только для улучшения сообщений об ошибках.

Если вы хотите, чтобы у mock были методы и свойства, вам нужно добавить их.

Если вы хотите автоматически создавать подделки, вы можете захватить FakeFactory из tsUnit, который создает фальшивую версию с некоторыми значениями по умолчанию что вы можете отказаться от переопределения - в JavaScript это довольно простой материал (плюс, не используя слишком много функциональных функций, вы можете убедиться, что вы тестируете поведение, а не реализацию).

Пример использования FakeFactory:

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

Ответ 2

Sinon может создать заглушку на основе конструктора довольно легко, если вместо mock вы используете метод createStubInstance.

Пример с использованием mocha, chai, sinon и sinon-chai, могли бы выглядеть например:

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  = <any> sinon.createStubInstance(MyStuff.MyService),
            controller = new MyStuff.MyController(myService, ...);

        // ... 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;
    });
});

Я опубликовал статью, которая может показаться вам полезной, если вы хотите узнать больше о разных тестовых двойниках и о том, как используйте их с Sinon.js.

Надеюсь, это поможет!

Jan