-1

I'm getting below errors. Why I'm receiving response as undefined from the service? Is there anything wrong I did for providing mock implementations?

enter image description here

Service:

export class SaveDataService{
    async save() : Promise<any> {
        try{
            return this.someFunction()
        } catch(ex){
            throw new Error('some error occured')
        }
    }

    async someFunction() : Promise<any>{
        const response = {
            "file" : "<htm><body>This is sample response</body></html>"
        }
        return Promise.resolve(response);
    }
}

Test/Spec file:

import { SaveDataService } from "./save-data.service";

jest.mock('./save-data.service')

describe('tests for SaveDataService', () => {

    it('when save method is called and success result is returned', async () => {
        let mockSaveDataServiceSomeFunction = jest.fn().mockImplementation(() => {
            return Promise.resolve('Success Result')
        }); 
        SaveDataService.prototype.someFunction = mockSaveDataServiceSomeFunction;

        let spy = jest.spyOn(SaveDataService.prototype, 'someFunction');

        let service = new SaveDataService();
        let data = await service.save()
        expect(data).toEqual('Success Result')
        expect(spy).toHaveBeenCalled()
    })

    it('when save method is called and error is returned', async () => {
        let mockSaveDataServiceSomeFunction = jest.fn().mockImplementation(() => {
            throw new Error('ERROR')
        }); 
        SaveDataService.prototype.someFunction = mockSaveDataServiceSomeFunction;

        let spy = jest.spyOn(SaveDataService.prototype, 'save');

        let service = new SaveDataService();
        service.save()
        expect(spy).toThrowError('ERROR')
    })
})
James Z
  • 12,209
  • 10
  • 24
  • 44
Tarun
  • 685
  • 3
  • 16
  • 1
    Don't mock parts of the thing you're supposed to be testing - test doubles are for _collaborators_. Test the _behaviour_, not the _implementation_. See e.g. https://stackoverflow.com/a/66752334/3001761 – jonrsharpe Aug 01 '21 at 07:29

1 Answers1

0

A mock replaces the dependency. You set expectations on calls to the dependent object, set the exact return values it should give you to perform the test you want, and/or what exceptions to throw so that you can test your exception handling code.

In this scenario, you are mocking save-data.service by calling jest.mock('./save-data.service'). So that your class may looks like this:

async save() : Promise<any>  {
  // do nothing or undefined
}

async someFunction() : Promise<any>  {
  // do nothing or undefined
}

So you must implement the body yourself to expect what exactly you want the method/function to do for you. You are mocking only the someFunction:

...

let mockSaveDataServiceSomeFunction = jest.fn().mockImplementation(() => {
    return Promise.resolve('Success Result')
}); 

SaveDataService.prototype.someFunction = mockSaveDataServiceSomeFunction;

...

So when you call the save() method you still get nothing/undefined.

You are overwriting the whole behavior of the service that I think your test may not be useful. But you can fix your test this way:

import { SaveDataService } from "./save-data.service";

jest.mock('./save-data.service');

describe('tests for SaveDataService', () => {
  beforeEach(() => {
    SaveDataService.mockClear();
  });

  it('when save method is called and success result is returned', async () => {
    const spy = jest
      .spyOn(SaveDataService.prototype, 'save')
      .mockImplementation(async () => Promise.resolve('Success Result'));

    const service = new SaveDataService();
    const data = await service.save();

    expect(data).toEqual('Success Result');
    expect(spy).toHaveBeenCalled();
  })

  it('when save method is called and error is returned', async () => {
    const spy = jest
      .spyOn(SaveDataService.prototype, 'save')
      .mockImplementation(() => {
        throw new Error('ERROR');
      });

    const service = new SaveDataService();
    expect(service.save).toThrowError('ERROR');
    expect(spy).toHaveBeenCalled();
  });
});
Ali Tavafi
  • 443
  • 1
  • 10
  • 28