Safe Mock is a library for Typescript (or Javascript) that allows mocks to be created from typescript interfaces or classes and utilized with simple typesafe syntax.
The syntax is inspired by Mockito.
Check out the examples below to get started:
npm install safe-mock
Then import it in your tests:
import SafeMock, {when, verify} from "safe-mock";
Create your first Safe Mock like this:
interface SomeService {
generate(key: string): string;
}
const mockSomeService = SafeMock.build<SomeService>();
Configure the mock to return values using SafeMock's when
when(mockSomeService.mockSomeService("key")).return("generatedKey");
when(mockSomeService.mockSomeService("other")).return("otherGeneratedKey");
Assert that mocks were used correctly with SafeMock's verify
verify(mock.mockSomeService).calledWith("key");
- SafeMock requires TypeScript 2.1 or later.
- SafeMock requires a Javascript runtime with support for the proxy object.
- If running on Node.js version 6+ is required.
Mocks can be created from an interface, class, or functions.
import SafeMock, {Mock} from "safe-mock";
interface SomeService {
createSomething(argument: number): string;
}
// mock an interface by passing the type of the mock as a generic to the build method
const mock: Mock<SomeService> = SafeMock.build<SomeService>();
// Typescript will infer the type so you don't need to specify the type of the mock
const mock = SafeMock.build<SomeService>();
import SafeMock, {Mock} from "safe-mock";
class SomeServiceClass {
createSomething(argument: number) {
return 106;
}
}
// mock a class by passing the class into the build method
const mock: Mock<SomeServiceClass> = SafeMock.build(SomeServiceClass);
// mock a class by passing the type of the mock as a generic to the build method
const mock: Mock<SomeServiceClass> = SafeMock.build<SomeServiceClass>();
//Typescript will infer the type so you don't need to specify the type of the mock
const mock = SafeMock.build<SomeService>();
import SafeMock, {Mock} from "safe-mock";
function someFunc() {
}
// Mock a function by passing it into the mockFunction method
const mockFunction = SafeMock.mockFunction(someFunc);
// if you have a type signature for a function you can use generics to create a mockFunction
type FunctionToMock = () => string;
const mockFunction = SafeMock.mockFunction<FunctionToMock>();
// you can pass a name into the mockFunction method to make debugging easier
type FunctionToMock = () => string;
const mockFunction = SafeMock.mockFunction<FunctionToMock>("nameOfFunc");
import SafeMock, {Mock, when} from "safe-mock";
interface SomeService {
someMethod(argument: number, otherArg: string): string;
}
const mock: Mock<SomeService> = SafeMock.build<SomeService>();
// specify return values only when mocks are called with certain arguments like this
when(mock.someMethod(123, "some arg")).return("expectedReturn");
// if you don't care what arguments a mock receives you can specify a return value for all calls
when(mock.someMethod).return("expectedReturn");
import SafeMock, {Mock, when} from "safe-mock";
interface SomeService {
someMethod(argument: number, otherArg: string): string;
}
const mock: Mock<SomeService> = SafeMock.build<SomeService>();
// specify thrown exceptions only when mocks are called with certain arguments like this
when(mock.someMethod(123, "some arg")).throw(new Error("BRR! Its cold!"));
//if you don't care what arguments a mock receives you can specify a thrown exceptions for all calls
when(mock.someMethod).throw(new Error("BRR! Its cold!"));
import SafeMock, {Mock, when} from "safe-mock";
interface SomeService {
someMethod(argument: number): Promise<string>;
}
const mock: Mock<SomeService> = SafeMock.build<SomeService>();
// specify that the mock returns rejected promises with a rejected value with reject
when(mock.someMethod(123)).reject(new Error("BRR! Its cold!"));
mock.someMethod(123); //returns Promise.reject(new Error("BRR! Its cold!"));
// specify that the mock returns resolved promises with resolve
when(mock.someMethod(124)).resolve("Hooray! You passed in 124");
mock.someMethod(124); //returns Promise.resolve("Hooray! You passed in 124");
Note: resolve() and reject() are only available on mocks that return a Promise.
import SafeMock, {verify} from "safe-mock";
interface SomeService {
someMethod(argument: number, otherArg: string): string;
}
const mock = SafeMock.build<SomeService>();
//use verify.calledWith to check the exact arguments to a mocked method
verify(mock.someMethod).calledWith(123, "someArg");
//use verify.called() to check that a mock was called at least once
verify(mock.someMethod).called();
//use verify.times(argument: number).called() to check that a mock was called a specified number of times
verify(mock.someMethod).times(2).called();
//use verify.times(argument: number).calledWith to check mocked method was called a specified number of times with
//the exact arguments
verify(mock.someMethod).times(4).calledWith(123, "someArg");
import SafeMock, {verify} from "safe-mock";
interface SomeService {
someMethod(argument: number): string;
}
const mock = SafeMock.build<SomeService>();
//use verify.never to check that a method was never called with any arguments.
verify(mock.someMethod).never.called();
//use verify.never.calledWith to check that a mock was never called with specific arguments
verify(mock.someMethod).never.calledWith(123);
import SafeMock, {verify} from "safe-mock";
interface SomeService {
someMethod(argument?: number, otherArg?: string): string;
}
const mock = SafeMock.build<SomeService>();
//use verify.unsafe when working with optional parameters
//unfortunately, type safety is lost when using 'verify.unsafe'
verify.unsafe(mock.someMethod).calledWith(123, "someArg");
verify.unsafe(mock.someMethod).calledWith(123);
verify.unsafe(mock.someMethod).called();
import SafeMock, {verify} from "safe-mock";
interface SomeService {
someMethod(argument: number, otherArg: string): string;
someOtherMethod(): string;
}
const mock = SafeMock.build<SomeService>();
//use resetMock() to a reset all methods on a mock
mock.resetMock()
//use resetMock() on an individual method to only reset that method
mock.someOtherMethod.resetMock()
import SafeMock, {verify, when} from "safe-mock";
function someFunction() {
return "string"
}
const mockFunction = SafeMock.mockFunction(someFunction);
when(mockFunction).return("return values");
verify(mockFunction).called()
someOtherMethod.resetMock();
SafeMock won't let you return the wrong type from mocks.
interface SomeService {
createSomething(): string;
}
const mock: Mock<SomeService> = SafeMock.build<SomeService>();
//Won't compile createSomething returns a string
when(mock.createSomething()).return(123);
SafeMock won't let you verify arguments of the wrong type.
interface SomeService {
createSomethingWithAString(argument: string): string;
}
const mock: Mock<SomeService> = SafeMock.build<SomeService>();
mock.createSomethingNoArgs();
//Won't compile, createSomething takes a string
verify(mock.createSomethingNoArgs).calledWith(123);
SafeMock won't let you verify the wrong number of arguments.
interface SomeService {
createSomethingNoArgs(): string;
}
const mock: Mock<SomeService> = SafeMock.build<SomeService>();
mock.createSomethingNoArgs();
//Won't compile, createSomething takes no args
verify(mock.createSomethingNoArgs).calledWith(123);
SafeMock won't let you verify non mocked methods.
const notAMock = {
blah() {}
};
//Won't compile notAMock.blah is not a mock
verify(notAMock.blah).called();