Testing is an important part of JavaScript.
In this article, we’ll look at how to create more complex tests with Jasmine.
Manually Failing a Spec With fail
We can call the fail
function to manually fail a test.
For instance, we can write:
describe("A suite", function () {
it("should fail", function () {
fail('failing test');
});
});
then we see that the test will fail.
Nesting describe
Blocks
We can have nested describe
blocks to let us describe more complex functionality.
Jasmine will walk down the tree to run the tests that are nested in the same order they’re written in.
beforeEach
will run before each test.
And afterEach
will run after each test.
For instance, we can write:
describe("A suite", function () {
let foo;
beforeEach(function () {
foo = 1;
});
afterEach(function () {
foo = 0;
});
it("foo is 1", function () {
expect(foo).toEqual(1);
});
it("can have more than one expectation", function () {
expect(foo).toEqual(1);
expect(true).toEqual(true);
});
describe("nested tests", function () {
let bar;
beforeEach(function () {
bar = 1;
});
it("can reference both scopes as needed", function () {
expect(foo).toEqual(bar);
});
});
});
We have a describe
block that’s nested in another describe
block.
The outer ones run first and then the inner ones will run once they’re reached by Jasmine.
Disabling Suites
We can disable suites by using xdescribe
.
For instance, we can write:
xdescribe("A spec", function () {
let foo;
beforeEach(function () {
foo += 1;
});
it("won't run", function () {
expect(foo).toEqual(1);
});
});
We have the xdescribe
function to disable the test suite.
So the tests won’t run.
Pending Specs
We can use the xit
function to disable a spec so that it won’t run.
For example, we can write:
describe("A spec", function () {
xit("can be declared 'xit'", function () {
expect(true).toBe(false);
});
it("has no expect");
it("is pending", function () {
expect(true).toBe(false);
pending('this is why it is pending');
});
});
We have the xit
function to make the specs pending.
Also, we can make a spec pending with the pending
function.
Spies
We can use spies to stub functions that we can use Jasmine to track calls and arguments.
For instance, we can write:
describe("A spy", function () {
let foo, bar;
beforeEach(function () {
foo = {
setBar(value) {
bar = value;
}
};
spyOn(foo, 'setBar');
foo.setBar('foo');
foo.setBar(1, 'bar');
})
it("tracks that the spy was called", function () {
expect(foo.setBar).toHaveBeenCalled();
});
it("tracks that the spy was called x times", function () {
expect(foo.setBar).toHaveBeenCalledTimes(2);
});
it("tracks all the arguments of its calls", function () {
expect(foo.setBar).toHaveBeenCalledWith('foo');
expect(foo.setBar).toHaveBeenCalledWith(1, 'bar');
});
it("stops all execution on a function", function () {
expect(bar).toBeUndefined();
});
it("tracks if it was called at all", function () {
foo.setBar();
expect(foo.setBar.calls.any()).toEqual(true);
});
});
We have the beforeEach
hook with the foo
object with the setBar
method.
In the hook, we call the spyOn
method to stub the setBar
method and then watch how it’s called and the result.
We can use the toHaveBeenCalled
matcher to check if the function is called.
Also, we can use toHaveBeenCalledTimes
to check how many times it’s been called.
The toHaveBeenCalledWith
method lets us check what parameters have the functions been called when they’re called.
calls.any()
lets us check if a spied on function has been called.
Conclusion
We can make tests pending and fail with built-in functions.
And we can spy on functions to see how they’re called.