How to change the MOCK implementation of a service per unit test

518 Views Asked by At

How to change the implementation of a mock depending on the test.

this is the code I am trying to unit test.

open(url: string, target: string = '_self'): void {
 const win = this.document.defaultView?.open(url, target);
 win?.focus();
}

And below my unit test

const MockDocument = {
  location: { replace: jest.fn() },
  defaultView: undefined
};

const createService = createServiceFactory({
  service: RedirectService,
  providers: [
   { provide: DOCUMENT, useValue: MockDocument }
 ]
});

My strategy is to set defaultView to undefined for the first test. And inside the next test, I would change the implementation to contain the open function, like this

const defaultView = {
open: jest
  .fn()
  .mockImplementation((url: string, target: string = '_self') => {
    url;
    target;
    return { focus: jest.fn().mockImplementation(() => {}) };
  })
};

const MockDocument = {
 location: { replace: jest.fn() },
 defaultView: defaultView
};

How do I change the implementation depending on the test?

Thanks for helping

EDIT

it('should not call "open" if defaultView is not truthy', () => {
  spectator.service.openFocus('foo');

  expect(mockDocument.defaultView).not.toBeTruthy();
});

it('should call "open" if defaultView is truthy', () => {
  //CHANGE THE IMPLEMENTATION HERE...
  const spy = jest.spyOn(mockDocument.defaultView, 'open')

  spectator.service.openFocus('foo');

  expect(spy).toHaveBeenCalled();
});
1

There are 1 best solutions below

4
Shafiq Jetha On

You can set defaultView up as a variable and change the variable speed test.

let defaultView: any;

const MockDocument = {
    location: { replace: jest.fn() },
    defaultView};

beforeEach(() => {
    ...
});

it('should not call "open" if defaultView is not truthy', () => {
    defaultView = undefined;
    expect(mockDocument.defaultView).not.toBeTruthy();
});

it('should call "open" if defaultView is truthy', () => {
    defaultView = {
        open: jest
        .fn()
        .mockImplementation((url: string, target: string = '_self') => {
            url;
            target;
            return { focus: jest.fn().mockImplementation(() => {}) };
        })
    };

    const spy = jest.spyOn(mockDocument.defaultView, 'open')

    expect(spy).toHaveBeenCalled();
});