Core Concepts

Advanced Mocking

Testing Multiple Calls of the Same Method

There are scenarios where we need to mock multiple calls of the same method, such as find(), but with different conditions. Let's explore an example to illustrate this:

In the following test case, I've used the toReturn() function twice for the find method of the "User" repository. The first call to find will return ["user1"], and the second call will return ["user2"]. If you need to simulate a third call to the find method, you can add another toReturn() function with the appropriate mock data.

describe('test suites', () => {
  it('test', async () => {
    const typeorm = new MockTypeORM()
    typeorm.onMock(User).toReturn(['user1'], 'find').toReturn(['user2'], 'find')

    const userRepo = dataSource.getRepository(User)
    const users = await userRepo.find({ where: { id: '1' } })
    const users2 = await userRepo.find({ where: { id: '2' } })

    expect(users).toEqual(['user1'])
    expect(users2).toEqual(['user2'])

    const firstUsersCalledWith = (userRepo.find as SinonSpy)
      .getCall(0)
      .calledWith({ where: { id: '1' } })
    const secondUsersCalledWith = (userRepo.find as SinonSpy)
      .getCall(1)
      .calledWith({ where: { id: '2' } })

    expect(firstUsersCalledWith).toBeTruthy()
    expect(secondUsersCalledWith).toBeTruthy()
  })
})

In this example, the toReturn() function chains two calls to find() with different mock data. The first call returns ["user1"] and the second returns ["user2"]. This chaining capability allows you to simulate different scenarios in your tests efficiently.

Additionally, to check what arguments were used when find() was first called, you can utilize Sinon as demonstrated in the test case above. This feature is particularly useful for verifying that methods were called with the expected arguments during testing.

Verifying Method Calls

Demonstrations on verifying method calls, checking arguments, and utilizing Sinon under the hood.

To check which arguments a function is called with:

describe('test suites', () => {
  it('test', async () => {
    const typeorm = new MockTypeORM()
    typeorm.onMock(User).toReturn(['user'], 'find')

    const userRepo = dataSource.getRepository(User)
    const users = await userRepo.find({ where: { id: '1' } })

    expect(users).toEqual(['user'])
    const calledWith = (userRepo.find as Sinon.SinonSpy).calledWith({
      where: { id: '1' },
    })
    expect(calledWith).toBeTruthy()
  })
})

Since all methods are wrapped with spies, you can easily check if a spy was called with specific arguments.

Since Mock TypeORM utilizes Sinon under the hood for mocking, you have the full power of Sinon at your disposal. This means you can perform all the tasks and verifications that Sinon allows, such as spying on method calls, checking arguments, stubbing method behaviors, and handling exceptions.

Previous
Basic Mocking