Testing is an important part of JavaScript.
In this article, we’ll look at how to create more complex tests with Jasmine.
createSpy
We can call createSpy
to stub a function.
They can be used to track arguments.
For instance, we can write:
describe("A spy", function () {
let spy;
beforeEach(function () {
spy = jasmine.createSpy('spy');
spy('foo', 'bar');
});
it("tracks that the spy was called", function () {
expect(spy).toHaveBeenCalled();
});
});
We created a spy with jasmine.createSpy
.
It returns a function that can be watched with Jasmine.
So we can check if it has been called with toHaveBeenCalled
.
createSpyObj
We can use the createSpyObj
method to create a mock with multiple spies.
For instance, we can write:
describe("Multiple spies", function () {
let person;
beforeEach(function () {
person = jasmine.createSpyObj('person', ['eat', 'drink', 'sleep', 'walk']);
person.eat();
person.drink();
person.sleep(0);
person.walk(0);
});
it("creates spies for each requested function", function () {
expect(person.eat).toBeDefined();
expect(person.drink).toBeDefined();
expect(person.sleep).toBeDefined();
expect(person.walk).toBeDefined();
});
});
We called createSpyObj
with the spy name as the first argument.
And the methods available in the spy object in the 2nd argument.
Then we can it and then check if the methods are defined
Matching and Spies
We can add more checks with more matches.
For instance, we can write:
describe("Tests", function () {
it("matches any value", function () {
expect({}).toEqual(jasmine.any(Object));
expect(12).toEqual(jasmine.any(Number));
});
describe("when used with a spy", function () {
it("is useful for comparing arguments", function () {
const foo = jasmine.createSpy('foo');
foo(12, () => true);
expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(Function));
});
});
});
We have can use toEqual
to check the type of a value with jasmine.any
.
We can use jasmine.any
with toHaveBeenCalledWith
to check if a spy is called with a given type of data.
jasmine.anything
We can use jasmine.anythibng
to check if something matches anything that’s not null
or undefined
.
For instance, we can write:
describe("jasmine.anything", function () {
it("matches anything", function () {
expect(1).toEqual(jasmine.anything());
});
describe("when used with a spy", function () {
it("is useful when the argument can be ignored", function () {
const foo = jasmine.createSpy('foo');
foo(12, 'bar');
expect(foo).toHaveBeenCalledWith(12, jasmine.anything());
});
});
});
We have jasmine.anything()
call to check if anything isn’t null
or undefined
.
Checking Object Structure
We can check for object structure with the jasmine.objectContaining
method.
For instance, we can write:
describe("jasmine.objectContaining", function () {
let foo;
beforeEach(function () {
foo = {
a: 1,
b: 2,
bar: "baz"
};
});
it("matches objects with key-value pairs", function () {
expect(foo).toEqual(jasmine.objectContaining({
a: 1, bar: "baz"
}));
});
describe("when used with a spy", function () {
it("is useful for comparing arguments", function () {
const callback = jasmine.createSpy('callback');
callback({
bar: "baz"
});
expect(callback)
.toHaveBeenCalledWith(
jasmine.objectContaining({
bar: "baz"
})
);
});
});
});
We have the jasmine.objectContaining
method to watch for object structure.
We just pass in the key-value pairs we want to check for.
It can be used with values and function arguments.
Conclusion
We can check for values and objects and watch for spies with various Jasmine methods.