My TypeORM repository extends
AbstractRepository:
@EntityRepository(User)
export class UsersRepository extends AbstractRepository<User> {
async findByEmail(email: string): Promise<User> {
return await this.repository.findOne({ email })
}
}
describe('UsersRepository', () => {
let usersRepository: UsersRepository
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersRepository]
}).compile()
usersRepository = module.get<UsersRepository>(UsersRepository)
})
describe('findByEmail', () => {
it(`should return the user when the user exists in database.`, async () => {
const fetchedUser = await usersRepository.findByEmail('test1@test.com')
})
})
})
Here, I get the error:
TypeError: Cannot read property 'getRepository' of undefined
at UsersRepository.get (repository/AbstractRepository.ts:43:29)
at UsersRepository.findByEmail (users/users.repository.ts:11:23)
at Object.<anonymous> (users/users.repository.spec.ts:55:49)
So, my question is, how do I mock the repository
or repository.findOne
?
In other words, how do I mock the fields that are inherited from the AbstractRepository
which are protected
and cannot be accessed from UsersRepository
instance?
There is a similar question here but it is for extending from Repository<Entity>
instead of AbstractRepository<Entity>
. They are able to mock findOne
because it's public
.
I tried to mock it in a NestJS recommended way, but this is for non-custom repositories and doesn't work in my case:
{
provide: getRepositoryToken(User),
useValue: {
findOne: jest.fn().mockResolvedValue(new User())
}
}
I went with the in-memory database solution. This way I don't have to mock the complex queries of TypeORM. The unit tests run as fast without hitting the real database.
My production database is PostgreSQL, but I'm able to use SQLite in-memory database for unit testing. This works because the TypeORM provides an abtraction over databases. It doesn't matter what database we are using under the hood as long as we are satisfying the interface of our repository.
Here's how my tests look like:
const testConnection = 'testConnection'
describe('UsersRepository', () => {
let usersRepository: UsersRepository
beforeEach(async () => {
const connection = await createConnection({
type: 'sqlite',
database: ':memory:',
dropSchema: true,
entities: [User],
synchronize: true,
logging: false,
name: testConnection
})
usersRepository = connection.getCustomRepository(UsersRepository)
})
afterEach(async () => {
await getConnection(testConnection).close()
})
describe('findByEmail', () => {
it(`should return the user when the user exists in database.`, async () => {
await usersRepository.createAndSave(testUser)
const fetchedUser = await usersRepository.findByEmail(testUser.email)
expect(fetchedUser.email).toEqual(testUser.email)
})
})
})