Jasmine — Spies and Matchers

John Au-Yeung - Jan 23 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

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();
  });
});
Enter fullscreen mode Exit fullscreen mode

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();
  });
});
Enter fullscreen mode Exit fullscreen mode

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));
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

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());
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

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"
          })
        );
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .