javascript - 타입 - Typescript-Interface/Type 정의를 스텁하는 법?




타입 스크립트 constructor (4)

나는 qUnit과 Sinon을 사용하여 Typescript 테스트를 작성해 왔으며 당신이 설명하는 것과 똑같은 고통을 경험했습니다.

다음과 같은 인터페이스에 의존한다고 가정 해 보겠습니다.

interface IDependency {
    a(): void;
    b(): boolean;
}

필자는 sinon 스텁 / 스파이와 캐스팅을 기반으로하는 몇 가지 접근법을 사용하여 추가 도구 / 라이브러리가 필요하지 않도록 관리했습니다.

  • 빈 객체 리터럴을 사용하고 코드에 사용 된 함수에 직접 sinon 스텁을 지정합니다.

    //Create empty literal as your IDependency (usually in the common "setup" method of the test file)
    let anotherDependencyStub = <IDependency>{};
    
    //Set stubs for every method used in your code 
    anotherDependencyStub.a = sandbox.stub(); //If not used, you won't need to define it here
    anotherDependencyStub.b = sandbox.stub().returns(true); //Specific behavior for the test
    
    //Exercise code and verify expectations
    dependencyStub.a();
    ok(anotherDependencyStub.b());
    sinon.assert.calledOnce(<SinonStub>anotherDependencyStub.b);
  • 코드에서 필요로하는 메소드의 빈 구현에 객체 리터럴을 사용한 다음 필요에 따라 sinon 스파이 / 스텁에 메소드를 래핑합니다.

    //Create dummy interface implementation with only the methods used in your code (usually in the common "setup" method of the test file)
    let dependencyStub = <IDependency>{
        a: () => { }, //If not used, you won't need to define it here
        b: () => { return false; }
    };
    
    //Set spies/stubs
    let bStub = sandbox.stub(dependencyStub, "b").returns(true);
    
    //Exercise code and verify expectations
    dependencyStub.a();
    ok(dependencyStub.b());
    sinon.assert.calledOnce(bStub);

qUnit 모듈에서 제공하는 것과 같은 sinon 샌드 박스 및 일반적인 설정 / 분해와 결합 할 때 매우 효과적입니다.

  • 공통 설정에서 새 샌드 박스를 만들고 mock 객체 리터럴을 종속성에 대해 만듭니다.
  • 테스트에서는 스파이 / 스텁을 지정합니다.

이런 식으로 (첫 번째 옵션을 사용하지만 두 번째 옵션을 사용하는 경우 같은 방식으로 작동합니다) :

QUnit["module"]("fooModule", {
    setup: () => {
        sandbox = sinon.sandbox.create();
        dependencyMock = <IDependency>{};
    },
    teardown: () => {
        sandbox.restore();
    }
});

test("My foo test", () => {
    dependencyMock.b = sandbox.stub().returns(true);

    var myCodeUnderTest = new Bar(dependencyMock);
    var result = myCodeUnderTest.doSomething();

    equal(result, 42, "Bar.doSomething returns 42 when IDependency.b returns true");
});

나는 이것이 여전히 이상적인 해결책이 아니라는 점에 동의 할 것이다. 그러나 그것은 합리적으로 잘 작동하고, 여분의 라이브러리를 필요로하지 않으며, 관리하기 어려운 수준으로 여분의 코드를 필요로한다.

저는 AngularJS 1.X 프로젝트에서 Typescript를 사용합니다. 다른 목적으로 다른 자바 스크립트 라이브러리를 사용합니다. 내 소스를 단위 테스트하려면 입력 (= 인터페이스)을 사용하여 일부 종속성을 스터핑하고 싶습니다. 나는 ANY 형을 사용하고 싶지 않고 각 인터페이스 메소드에 대해 빈 메소드를 작성하지도 않는다.

나는 그런 식으로 할 수있는 방법을 찾고있다.

let dependency = stub(IDependency);
stub(dependency.b(), () => {console.log("Hello World")});
dependency.a(); // --> Compile, do nothing, no exception
dependency.b(); // --> Compile, print "Hello World", no exception

지금 당장 가지고있는 고통은 테스트 케이스에서 호출 된 모든 메소드를 구현하고 구현하거나 인터페이스를 구현하고 전체 인터페이스를 구현한다는 것입니다. 너무 쓸모없는 코드입니다. (.

각 메소드에 대해 빈 구현이 있고 유형이 지정된 객체를 생성하려면 어떻게해야합니까? 나는 조롱 목적으로 시논 (Sinon)을 사용하지만 다른 라이브러리도 사용하기 위해 열어 둡니다.

추신 : 저는 Typescript가 인터페이스를 지우고 있다는 것을 알고 있습니다 ...하지만 여전히 해결하고 싶습니다 :).


당신은 moq.ts 를 시도 할 수 있지만 Proxy 객체에 의존한다.

interface IDependency {
  a(): number;
  b(): string;
}


import {Mock, It, Times} from 'moq.ts';

const mock = new Mock<IDependency>()
  .setup(instance => instance.a())
  .returns(1);

mock.object().a(); //returns 1

mock.verify(instance => instance.a());//pass
mock.verify(instance => instance.b());//fail

최신 TypeMoq (ver 1.0.2)는 런타임 (nodejs / browser)이 ES6에서 도입 된 Proxy 전역 객체를 지원하는 한 TypeScript 인터페이스 조롱을 지원합니다.

따라서, IDependency 다음과 같이 가정합니다.

interface IDependency {
    a(): number;
    b(): string;
}

TypeMoq로 조롱하면 다음과 같이 간단합니다.

import * as TypeMoq from "typemoq";
...
let mock = TypeMoq.Mock.ofType<IDependency>();

mock.setup(x => x.b()).returns(() => "Hello World");

expect(mock.object.a()).to.eq(undefined);
expect(mock.object.b()).to.eq("Hello World");

TypeMoq , TeddyMocksTypescript-mockify 를 수행 할 수있는 라이브러리는 거의 없다.

github 리포지토리를 확인하고 더 좋아하는 링크를 선택하십시오. 링크 :

Sinon과 같은 더 많이 사용하는 라이브러리를 사용할 수도 있지만 먼저 <any> 유형을 사용하고 <IDependency> 유형으로 범위를 좁혀 야합니다 ( Sinon을 Typescript와 함께 사용하려면 어떻게해야합니까? ).





stubbing