Update:
for now I solved it by creating the class a Singleton but am told not an ideal way/pattern.
This answer seems to have it all but for the life of me, I can't figure out why my test is failing. The app simply:
Datatabase.js : a class that is not directly accessed by components and works with sqllite
class Database {
........
}
MembersService.js
class MembersService {
_db = new Database();
getMembers = async () => {
try {
const members = await this._db.getMembers();
}
catch (e){
}
}
}
now I have a component that makes use of MembersService button click.
handleListMembers = async () =>{
console.log('button clicked')
const members = await membersService.getMembers();
updateMembers(members)
}
now I want to test the button click and mock with my mocked members. I want the getMembers method of membersService to return empty result but so far I can't. My test fails when I do:
expect(spy).toHaveBeenCalled()
I tried the following:
const spy = jest.spyOn(MembersService.prototype, 'getMembers')
//fails with Cannot spy the getMembers property because it is not a function; undefined given instead. console.log(MembersService.prototype) returns {}
// second attempt: no error but never gets called. I get data that is stored in sqllite instead of an empty list
const service = new MembersService();
const spy = jest.spyOn(service, 'getMembers');
spy.mockResolvedValue([])
//third
const service = new MembersService();
const spy = jest.spyOn(service, 'getMembers').mockImplementation(() => Promise.resolve([]));
So far the only way I can get an actual empty resutlset is if I mock the Database class itself but none of my components import the class and i don't think my tests should. What am I doing wrong?
it('should render members on button click', async () => {
const service = new MembersService();
const spy = jest.spyOn(service, 'getMembers').mockResolvedValue([])
const wrapper = render(
<MembersScreen testID="MembersScreen" />,
);
//wait for the component to load. it contains button with testID listMembers
await act(async () => {
await flushMicrotasksQueue();
});
// click the button now
const btn = wrapper.getByTestId('listMembers');
fireEvent.press(btn);
await act(async () => {
await flushMicrotasksQueue();
});
expect(spy).toHaveBeenCalled();
})
I can see button clicked in my console so the button is being pressed in my test.