Reputation: 59
This is users.service.ts
@Injectable()
export class UserService {
constructor(
@InjectRepository(User) private readonly users: Repository<User>,
@InjectRepository(Verification)
private readonly verifications: Repository<Verification>,
private readonly jwtService: JwtService,
private readonly mailService: MailService,
) {}
async findById(id: number): Promise<UserProfileOutput> {
try {
const user = await this.users.findOneOrFail({ id });
return {
ok: true,
user: user,
};
} catch (error) {
return { ok: false, error: 'User Not Found' };
}
}
I'm using TypeORM's Repository API(e.g. users.findOne, users.find, users.delete, etc). And The below file is a test file to test "users.service".
This is "users.service.spec.ts"
const mockRepository = () => ({
findOne: jest.fn(),
findOneOrFail: jest.fn(),
save: jest.fn(),
create: jest.fn(),
delete: jest.fn(),
});
const mockJwtService = {
sign: jest.fn(() => 'signed-token'),
verify: jest.fn(),
};
const mockMailService = () => ({
sendVerificationEmail: jest.fn(),
});
type MockRepository<T = any> = Partial<Record<keyof Repository<T>, jest.Mock>>;
describe('UserService', () => {
let service: UserService;
let usersRepository: MockRepository<User>;
let verificationsRepository: MockRepository<Verification>;
let mailService: MailService;
let jwtService: JwtService;
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
UserService,
{
provide: getRepositoryToken(User),
useValue: mockRepository(),
},
{
provide: getRepositoryToken(Verification),
useValue: mockRepository(),
},
{
provide: JwtService,
useValue: mockJwtService,
},
{
provide: MailService,
useValue: mockMailService(),
},
],
}).compile();
service = module.get<UserService>(UserService);
mailService = module.get<MailService>(MailService);
jwtService = module.get<JwtService>(JwtService);
usersRepository = module.get(getRepositoryToken(User));
verificationsRepository = module.get(getRepositoryToken(Verification));
});
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('findById', () => {
it('should fail if user is not found', async () => {
usersRepository.findOneOrFail.mockRejectedValue(new Error());
const result = await service.findById(1);
expect(result).toEqual({
ok: false,
error: 'User Not Found',
});
});
it('should find an existing user', async () => {
const findByIdArgs = {
id: 1,
};
usersRepository.findOneOrFail.mockResolvedValue(findByIdArgs);
const result = await service.findById(1);
expect(result).toEqual({
ok: true,
user: findByIdArgs,
});
});
});
What if I switch to use TypeORM's querybuilder method.
async findByIdWithQueryBuilder(id: number): Promise<UserProfileOutput> {
try {
const user = await this.users
.createQueryBuilder('user')
.where('bundle.id = :id', { id })
.getOneOrFail();
return {
ok: true,
user,
};
} catch (error) {
return { ok: false, error: 'User Not Found' };
}
}
The question is How can I mock QueryBuilder's chaining methods?
I tried
const mockRepository = () => ({
findOne: jest.fn(),
findOneOrFail: jest.fn(),
save: jest.fn(),
create: jest.fn(),
delete: jest.fn(),
createQueryBuilder: jest.fn(() => ({
delete: () => jest.fn().mockReturnThis(),
innerJoinAndSelect: () => jest.fn().mockReturnThis(),
innerJoin: () => jest.fn().mockReturnThis(),
leftJoinAndSelect: () => jest.fn().mockReturnThis(),
leftJoin: () => jest.fn().mockReturnThis(),
from: () => jest.fn().mockReturnThis(),
where: () => jest.fn().mockReturnThis(),
orWhere: () => jest.fn().mockReturnThis(),
andWhere: () => jest.fn().mockReturnThis(),
execute: () => jest.fn().mockReturnThis(),
orderBy: () => jest.fn().mockReturnThis(),
take: () => jest.fn().mockReturnThis(),
skip: () => jest.fn().mockReturnThis(),
getOne: () => jest.fn(),
getMany: () => jest.fn(),
getManyAndCount: () => jest.fn(),
})),
});
I got stuck here...
What would be the proper way to mock the chaining methods of QueryBuilder api?
Upvotes: 3
Views: 4242
Reputation: 36
you may use jest.spyOn for the QueryBuilder
prototype
like this:
import { QueryBuilder } from 'typeorm';
describe('Name of the group', () => {
it('should do something', () => {
const queryBuilder: any = {
into: jest.fn().mockReturnThis(),
values: jest.fn().mockReturnThis(),
onConflict: jest.fn().mockReturnThis(),
setParameter: jest.fn().mockReturnThis(),
execute: jest.fn().mockRejectedValueOnce(new Error('db Error')),
// execute: jest.fn().mockResolvedValueOnce({ res: 'mockRes' }),
};
jest
.spyOn(QueryBuilder.prototype, 'insert')
.mockReturnValueOnce(queryBuilder);
});
});
function usage
export async function doQuery(input: any){
const queryRunner = await Entity.createQueryRunner();
await queryRunner.manager
.createQueryBuilder()
.insert()
.into(Entity)
.values(input)
.onConflict(
`("id") DO UPDATE SET "date" = :date`
)
.setParameter('date', date)
.execute();
}
Upvotes: 2