How to stub a Typescript-Interface / Type-definition? How to stub a Typescript-Interface / Type-definition? angularjs angularjs

How to stub a Typescript-Interface / Type-definition?


I have been writing Typescript tests using qUnit and Sinon, and I have experienced exactly the same pain you are describing.

Let's assume you have a dependency on an interface like:

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

I have managed to avoid the need of additional tools/libraries by using a couple of approaches based on sinon stubs/spies and casting.

  • Use an empty object literal, then directly assign sinon stubs to the functions used in the code:

    //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 hereanotherDependencyStub.b = sandbox.stub().returns(true); //Specific behavior for the test//Exercise code and verify expectationsdependencyStub.a();ok(anotherDependencyStub.b());sinon.assert.calledOnce(<SinonStub>anotherDependencyStub.b);
  • Use object literal with empty implementations of the methods needed by your code, then wrap methods in sinon spies/stubs as required

    //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/stubslet bStub = sandbox.stub(dependencyStub, "b").returns(true);//Exercise code and verify expectationsdependencyStub.a();ok(dependencyStub.b());sinon.assert.calledOnce(bStub);

They work quite nice when you combine them with sinon sandboxes and common setup/teardown like the one provided by qUnit modules.

  • In the common setup you create a new sandbox and the mock object literals for your dependencies.
  • In the test you just specify the spies/stubs.

Something like this (using the first option, but would work the same way if you were using the second option):

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");});

I would agree this is still not the ideal solution but it works reasonably well, doesn't require extra libraries and keeps the amount of extra code needed to a low manageable level.


Latest TypeMoq (ver 1.0.2) supports mocking TypeScript interfaces, as long as the runtime (nodejs/browser) supports the Proxy global object introduced by ES6.

So, assuming IDependency looks like this:

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

then mocking it with TypeMoq would be as simple as this:

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");


I think the short answer is that this is not possible in Typescript, as the language offers no compile-time or run-time "reflection". It's not possible for a mock library to iterate the members of an interface.

See thread: https://github.com/Microsoft/TypeScript/issues/1549

This is unfortunate for TDD developers, in which mocking a dependency is a central part of the development workflow.

There are a number of techniques for quickly stubbing the methods, however, as described by the other answers. These options might do the job, with a little mental adjustment.

Edit: The Typescript Abstract Syntax Tree, AST, is a compile-time "introspection" - which could probably be used to generate mocks. However, I don't know if anyone has made a practical library.