Search code examples
typescriptjestjstypeorm

jest mock does not see that it has been called inside if statement in function


I am using typescript with typeORM and I have a jest test that looks as followed:

    test('add test', async () => {
        testRepoMock = {
            innerTestRepo: ({
                findOne: jest.fn().mockReturnValue(null),
                create: jest.fn().mockReturnValue({ id: 2 }),
            } as unknown) as Repository<ValuesModel>,
        };

        TestService.addvalue(id, testRepoMock);

        expect(testRepoMock.innerTestRepo.findOne).toHaveBeenCalledTimes(1);
        expect(testRepoMock.innerTestRepo.create).toHaveBeenCalledTimes(1);
    });

The function I'm testing looks like this:

    static async addvalue(
        id: number,
        repos?: { innerTestRepo: Repository<ValuesModel> },
    ): Promise<Values> {
        let repo;
        if (repos) {
            // basically use our mocks if this is a unit test
            repo = repos.innerTestRepo;
        } else {
            repo = await SqlDb.getRepository(ValuesModel);
        }

        let perms = await repo.findOne({ id });

        if (!perms) {
            perms = repo.create();
            perms = {
                ...perms,
            };
            await repo.save(perms);
        }

        return perms;
    }

What I cannot figure out is that the expect(testRepoMock.innerTestRepo.create).toHaveBeenCalledTimes(1); keeps reporting that testRepoMock.innerTestRepo.create was never called, even though I can log that perms is set to {id:2} via the mock and that the if statement is indeed entered.

I even checked what happened if I move the repo.create out of that if statement as a sanity check and then the test passes, so it looks like something about the scope of the if statement confuses jest such that it does not realize that create has been called.


Solution

  • You need to add await when you call addValue, otherwise your expect lines will be executed before the functions are actually executed

    test('add test', async () => {
        testRepoMock = {
            innerTestRepo: ({
                findOne: jest.fn().mockReturnValue(null),
                create: jest.fn().mockReturnValue({ id: 2 }),
            } as unknown) as Repository<ValuesModel>,
        };
    
        await TestService.addvalue(id, testRepoMock);
    
        expect(testRepoMock.innerTestRepo.findOne).toHaveBeenCalledTimes(1);
        expect(testRepoMock.innerTestRepo.create).toHaveBeenCalledTimes(1);
    });