Jest has a similar structure to Jasmine.
describe("<MeaningOfLife />", () => {
describe("askQuestion", () => {
let answer;
beforeEach(() => {
answer = askQuestion();
});
it("gives the answer to everthing", () => {
expect(answer).toEqual(42);
});
});
});
Here are the docs with a complete list of matchers.
expect(value).toEqual(23);
expect(arr).toHaveLength(5);
expect(nullVal).toBeNull();
expect(myObj).toHaveProperty("firstName", "JimBob");
expect(myObj.foo).toBeUndefined();
expect(result).toBeCloseTo(3.14159);
You can negate any of them with the not
method chain:
expect(value).not.toEqual(23);
If you want to focus an it
or a describe
section, use only
it.only("verifies coolness", () => {
const coolSpy = jest.spyOn(elliotIs, "cool");
elliotIs.cool();
expect(coolSpy).toHaveBeenCalled();
});
You can mock a method and then test that it was called:
const doSomething = jest.fn();
it("did something", () => {
doSomething('please');
expect(doSomething.mock.calls.length).toEqual(1);
expect(doSomething.mock.calls[0][0]).toEqual("please");
expect(doSomething).toHaveBeenCalledTimes(1);
expect(doSomething).toHaveBeenCalledWith("please");
});
You can also spy on a method:
const elliotIs = { cool: () => {} };
it("verifies coolness", () => {
const coolSpy = jest.spyOn(elliotIs, "cool");
elliotIs.cool();
expect(coolSpy).toHaveBeenCalled();
});
Creates a mock function similar to jest.fn but also tracks calls to object[methodName]. Returns a Jest mock function.
Note: By default, jest.spyOn also calls the spied method. This is different behavior from most other test libraries.
mockClear
resets all information stored in the mockFn.mock.calls
and mockFn.mock.instances
arrays.
Often this is useful when you want to clean up a mock's usage data between two assertions.
const mockFn = jest.fn();
// some tests
mockFn.mockClear()
mockReset
resets all information stored in the mock, including any initial implementation and mock name given.
This is useful when you want to completely restore a mock back to its initial state.
const mockFn = jest.fn();
// some tests
mockFn.mockReset()
mockRestor
removes the mock and restores the initial implementation.
This is useful when you want to mock functions in certain test cases and restore the original implementation in others.
const mockFn = jest.fn();
// some tests
mockFn.mockRestor()
Note:
jest.fn(implementation)
is a shorthand forjest.fn().mockImplementation(implementation)
You can add a standin implementation for a mock
const meaningOfLife = jest.fn(() => 42);
You can also mock the implementation once, so the first time the mock is called, it will return the mock implementation, and then after that, the original functionality is used. These can be chanined:
const meaningOfLife = jest
.fn(() => "I mean, it's a silly question, really")
.mockImplementationOnce(() => "42")
.mockImplementationOnce(() => "I mean it, 42")
console.log(meaningOfLife(), meaningOfLife(), meaningOfLife(), meaningOfLife())
// => 42
// => I mean it, 42
// => I mean, it's a silly question, really
// => I mean, it's a silly question, really
You can use mockReturnValue
instead of jest.fn(() => 42)
const mock = jest.fn().mockReturnValue(42);
mock(); // 42
If you are testing a class that has imports you would like to mock out, you can use jest.mock
Implementation:
import knowledge from "google";
class MeaningOfLife {
ask() {
const googleThinks = knowlege.meaningOfLife;
return `${googleThinks}, or 42`;
}
}
Test, this mocks out google
in the implementation file.
import MeaningOfLife from "./meaning-of-life";
import knowledge from "google";
jest.mock("google");
To execute the whole suite
$ jest test
To execute the whole suite with coverage
$ jest test --coverage
This will create a coverage report in coverage/lcov-report/index.html
To run the suite in watch mode, where it will re-run everytime a file is saved
$ jest test --watchAll
To run for a single file
$ jest test MyComponent.spec.js
To watch the one file
$ jest test --watch MyComponent.spec.js
Using the Enzyme library from AirBnb can help make React component testing better.
Snapshot testing with Enzyme is a bit simpler than with vanilla Jest
describe("<Foo />", () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<Foo />);
});
describe("snapshot", () => {
it("renders correctly", () => {
expect(wrapper).toMatchSnapshot();
});
});
});
Once you've used shallow
to render the component, you can interact with it in a few useful ways.
wrapper.setState({ foo: "bar" });
wrapper.state("foo");
wrapper.setProps({ foo: "bar" });
The shallow render is just a shallow rendered instance of the component class. The instance of this object is available with wrapper.instance()
. Off of this you can work with methods and data on the class.
This can be useful for properties that are not a part of the object's state
class Foo extends Component {
constructor(props) {
super(props);
this.foo = "bar";
}
}
// ... then in your test
wrapper.instance().foo; // bar
This can also be a useful way to mock out methods
class Foo extends Component {
myMethod() {
// does some stuff
}
}
// ... then in your test
const myMethodMock = jest.fn();
wrapper.instance().myMethod = myMethodMock;
// ... some testing stuff that calls myMethod()
expect(myMethodMock).toHaveBeenCalledTimes(1);
You can also use the shallow wrapper to find rendered elements and simulate events on them
wrapper.find("button").simulate("click");
expect(onButtonClickMock).toHaveBeenCalledTimes(1);
The mount renderer does a full DOM render. You need this if you are testing methods that deal with references.
describe("mouseEnterHandler", () => {
it("sets the style transform property of myRef", () => {
wrapper = mount(<Foo {...defaultProps} />);
wrapper.instance().mouseEnterHandler("event-stub");
expect(
wrapper.instance().myRef.current.style.transform
).toEqual("rotate(0deg) translate(-50%, -50%)");
});
});