Jasmine — Custom Spies
Tags: webdev, programming, testing, javascript
Published: 2021-01-23 20:53:21

**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 custom spies.

### Custom Spies

We can use the `jasmine.setDefaultSpyStrategy` to create a spy that does what we want.

For instance, we can write:

```
describe("spy tests", function () {
  beforeEach(function () {
    jasmine.setDefaultSpyStrategy(and => and.returnValue("Hello World"));
  }); 

  it('calls custom spy', function () {
    const spy = jasmine.createSpy();
    expect(spy()).toEqual("Hello World");
  });
});
```

We called `setDefaultSpyStrategy` with a callback that returns the `'Hello World'` value.

Once we did that, our spy would return `'Hello world'` .

So when we call `spy` , it returns `'Hello World'` .

Also, we can call `setDefaultSpyStrategy` with no arguments to remove a custom default.

For instance, we can write;

```
describe("spy tests", function () {
  beforeEach(function () {
    jasmine.setDefaultSpyStrategy(and => and.returnValue("Hello World"));
  }); 

  it('calls custom spy', function () {
    const spy = jasmine.createSpy();
    expect(spy()).toEqual("Hello World");
  }); 

  it("throws if you call any methods", function () {
    jasmine.setDefaultSpyStrategy(and => and.throwError(new Error("Do Not Call Me")));
    const program = jasmine.createSpyObj(['start']);
    jasmine.setDefaultSpyStrategy(); expect(() => {
      program.start();
    }).toThrowError("Do Not Call Me");
  });
});
```

We called `createSpyObj` in the 2nd test to include a `'start'` method in the `porgram` spy object.

Then we can check if an error is thrown with we call `start` .

### Spying on Properties

We can spy on properties with the `spyOnProperty` method.

For instance, we can write:

```
describe("property spy test", function () {
  let someObject = {
    get myValue() {
      return 1
    }
  }; 

  beforeEach(function () {
    this.propertySpy = spyOnProperty(someObject, "myValue", "get").and.returnValue(1);
  }); 

  it("lets you change the spy strategy later", function () {
    this.propertySpy.and.returnValue(3);
    expect(someObject.myValue).toEqual(3);
  });
});
```

We created a `someObject` with the `myValue` getter to return something.

Then in the `beforeEach` hook, we call `spyOnPropoerty` spy on the object and return the mocked value we want.

In our test, we called `returnValue` to make the getter return another value.

And then we can check for the return value we just set.

We can also spy on an object with several properties on it by passing in a hash of properties.

For instance, we can write:

```
describe("property spy test", function () {
  it("lets you change the spy strategy later", function () {
    const obj = jasmine.createSpyObj("myObject", {}, { x: 3, y: 4 });
    expect(obj.x).toEqual(3); 
    Object.getOwnPropertyDescriptor(obj, "x").get.and.returnValue(7);
    expect(obj.x).toEqual(7);
  });
});
```

We create a spy object with some properties.

It has the `x` and `y` properties.

Then we can check for `obj.x` and return the value we want.

And then we can check for it.

### Conclusion

There are different ways to spy on objects and return values.

We can create spy objects and set the spy strategy to what we want.