Jest mocks for unit tests for TypeScript classes. This will allow you to easily mock TypeScript classes, (which are similar to ES6 classes). It also has automatic instantiation and mocking of a class' dependencies.
The mocks generated are type-safe with deep typing, allowing for TypeScript to catch any syntax or type errors, and modern code-completing editors to help with writing testss
const classMockInstance = generateMockInstance(ClassA);
classMockInstance.method1('abc');
expect(classMockInstance.method1).toHaveBeenCalled();
expect(classMockInstance.method1.mock.calls).toEqual([['abc']]);
const {classInstance, dependencies, resetAllMocks} = instantiateWithMocks(ClassA, {ClassB, ClassC});
classInstance.methodThatReliesOnDependencies('abc');
expect(dependencies.ClassB.method1).toHaveBeenCalled();
expect(dependencies.ClassC.method2).toHaveBeenCalled();
All you need to do is install the package (see below) and import
This project uses Jest for its mock functions. Technically, you can use it in a project using a different testing framework, but it is not intended for such.
To install, all you need to do is:
npm install jest-class-mocker
And then
import {generateMockInstance, instantiateWithMocks} from "jest-class-mocker";
Then use these functions as per the API below.
This function takes a class constructor and returns a type-safe mocked class instance with all of the instance methods of that class.
Use the generic type syntax <ClassTypeToMock>
(see the example below) to ensure a fully type-safe return value.
Param | Type | Description |
---|---|---|
ClassConstructor | constructor function |
the function that is used with new |
MockOf<ClassTypeToMock>
This is a type defined by the package. It includes all of the methods and properties of a normal class instance of ClassToMock
, plus the mockReset
function which resets all of the mocked functions.
class ClassA {
property1 = 1;
method1(arg1: string): string {
return arg1 + 'abc';
}
}
const classMockInstance = generateMockInstance<ClassA>(ClassA);
classMockInstance.method1.mockReturnValue('mockRetVal');
const retVal = classMockInstance.method1('abc');
expect(classMockInstance.method1).toHaveBeenCalled();
expect(classMockInstance.method1.mock.calls).toEqual([['abc']]);
expect(retVal).toEqual('mockRetVal');
Note: This only creates mock instance methods. While the instance properties of the class are part of the TypeScript type definition, their values will be undefined
during runtime unless set explicitly:
const classAMock = generateMockInstance<ClassA>(ClassA);
expect(classAMock.function1).toBeDefined();
expect(classAMock.property1).toBeUndefined();
instantiateWithMocks(ClassToInstantiate, dependencyClasses) ⇒ {classInstance, dependencies, resetAllMocks}
This function takes a class constructor and its dependency class constructor and returns a class instance,
plus mock instances (using generateMockInstance
) with all of the instance methods of that class.
It also returns a convenience method for resetting all functions in all dependencies.
Param | Type | Description |
---|---|---|
ClassToInstantiate | constructor function |
the function that is used with new to create the class you want to instantiate. |
dependencies | object literal of constructor functions OR values to use for dependencies |
Class constructor in an object literal, using the class name as the key. See the example below. |
Param | Type | Description |
---|---|---|
classInstance | instance of ClassToInstantiate |
A new instance of ClassToInstantiate , using mocked instances for its dependencies. |
dependencies | object literal containing mocks of all passed dependencies |
The mocked instances used to create classInstance |
resetAllMocks | () => void |
A convenience function, equivalent to calling mockReset() on each of the dependencies. |
Important Note:
This function relies on Object keys being ordered, and therefore, the dependencies must be passed in the order that the class expects to receive them as parameters.
class ClassA {
function1(): string {
return 'abc';
}
}
class ClassB {
function2(): string {
return 'def';
}
}
class ClassC {
constructor(
private name: 'abc',
private classA: ClassA,
private classB: ClassB
) {}
functionThatReliesOnDependencies() {
return this.classA.function1() + this.classB.function2();
}
}
const {classInstance, dependencies, resetAllMocks} = instantiateWithMocks(ClassC, {name: 'abc', ClassA, ClassB});
expect(dependencies.ClassA).toBeDefined();
expect(dependencies.ClassB).toBeDefined();
dependencies.ClassA.function1.mockReturnValue('first');
dependencies.ClassB.function2.mockReturnValue('second');
const result = classInstance.functionThatReliesOnDependencies();
expect(dependencies.ClassA.function1).toHaveBeenCalled();
expect(dependencies.ClassB.function2).toHaveBeenCalled();
expect(result).toEqual('firstsecond');
- Ilan Cohen - Initial work - Ilan Cohen
This project is licensed under the MIT License - see the LICENSE.md file for details
- Thanks to ffMathy from whose Substitute project I borrowed (with permission) some advanced TypeScript types.
- Special thanks to Ben Grynhaus for helping me muddle through some of the more complicated aspects of advanced TypeScript types.