Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock a typescript interface with jest

Is it possible to mock a typescript interface with jest?

For example:

import { IMultiplier } from "./IMultiplier";  export class Math {   multiplier: IMultiplier;    public multiply (a: number, b: number) {     return this.multiplier.multiply(a, b);   } } 

Then in a test:

import { Math } from "../src/Math"; import { IMultiplier } from "../src/IMultiplier";  describe("Math", () => {      it("can multiply", () => {         let mathlib = new Math();         mathlib.multiplier = // <--- assign this property a mock         let result = mathlib.multiply(10, 2);         expect(result).toEqual(20);     }); }); 

I've tried to create a mock object to satisfy this a number of ways, but none work. For example assigning it this mock:

let multiplierMock = jest.fn(() => ({ multiply: jest.fn() })); 

Will produce something along the lines of:

Error - Type 'Mock<{ multiply: Mock<{}>; }>' is not assignable to type 'IMultiplier'. 
like image 770
Cuthbert Avatar asked Aug 31 '18 20:08

Cuthbert


People also ask

Can you mock an interface?

The Mockito. mock() method allows us to create a mock object of a class or an interface. We can then use the mock to stub return values for its methods and verify if they were called.

Does Jest clear mocks?

mockClear() does, and also removes any mocked return values or implementations. This is useful when you want to completely reset a mock back to its initial state. (Note that resetting a spy will result in a function with no return value).

Can I use Jest mock inside a test?

mock() doesn't work inside tests, only outside tests. Bookmark this question.


2 Answers

I created a library which allows you to mock out TypeScript interfaces - https://github.com/marchaos/jest-mock-extended.

There didn't seem to be libs that does this cleanly whilst keeping full type safety. It's based loosely on the discussion here -https://github.com/facebook/jest/issues/7832

like image 181
marchaos Avatar answered Sep 21 '22 08:09

marchaos


The mock just needs to have the same shape as the interface.

(from the docs: One of TypeScript’s core principles is that type-checking focuses on the shape that values have. This is sometimes called “duck typing” or “structural subtyping”.)

So mathlib.multiplier just needs to be assigned to an object that conforms to IMultiplier.

I'm guessing that IMultiplier from the example looks something like this:

interface IMultiplier {   multiply(a: number, b: number): number } 

So the example test will work fine by changing the line in question to this:

mathlib.multiplier = {   multiply: jest.fn((a, b) => a * b) }; 
like image 43
Brian Adams Avatar answered Sep 19 '22 08:09

Brian Adams