-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
question: how to mock InjectRepository
?
#33
Comments
This is what I ended up doing and it works well for most test cases - I created a mock repository - export class MockRepository {
static singletonList: MockRepository[] = [];
static getInstance(repository?: Function | string) {
let repositoryString: string;
if (!repository) repositoryString = 'default';
else if (typeof repository === 'string') repositoryString = repository;
else repositoryString = repository.name;
if (!MockRepository.singletonList[repositoryString])
MockRepository.singletonList[repositoryString] = new MockRepository();
return MockRepository.singletonList[repositoryString];
}
public find: Function;
public findOne: Function;
public save: Function;
private constructor() {
this.find = jest.fn();
this.findOne = jest.fn();
this.save = jest.fn();
}
} and use it in my MockUtils - import * as typeOrm from 'typeorm';
import Container from 'typedi';
import { MockRepository } from './mocks/repository.mock';
import { MockIoRedis } from './mocks/ioredis.mock';
export class MockUtils {
static mockOrm() {
Object.defineProperty(typeOrm, 'getRepository', {
value: (x: Function) => {
return MockRepository.getInstance(x.name);
},
});
jest.mock('typeorm-typedi-extensions', () => ({
InjectRepository: (entityTypeOrConnectionName?: Function | string) => (
object: object,
propertyName: string,
index?: number,
) => {
Container.registerHandler({
index,
object,
propertyName,
value: () => MockRepository.getInstance(entityTypeOrConnectionName),
});
},
}));
}
static mockRedis() {
jest.mock('ioredis', () => MockIoRedis);
}
} Just stick |
Is there an easier solution than presented above? |
@pbn4 not sure what is your use case, but when I first discovered this issue, what I was doing is I was extending What I am doing now instead is I create a separate class, annotate it as a |
After reading the source code of the resolver class likes look that, we need to focus on the property name injected by // resolver.ts
@Service()
export class RegisterResolver {
// another service
@Inject('REGISTER_SERVICE')
private readonly registerService!: RegisterService;
// the orm repository
@InjectRepository(User)
private readonly userRepository!: Repository<User>;
} the test file looks like: import Container from 'typedi';
import { RegisterResolver } from '@root/modules/user/register/register.resolver';
describe('test register resolver', () => {
test('test', async () => {
// mock the orm operations used in resolver;
const saveMock = jest.fn();
const createMock = jest.fn().mockImplementation(input => ({
...input,
id: 1,
}));
// mock the register service;
sendEmail = jest.fn();
getUrl = jest.fn();
// replace actual service
Container.set('REGISTER_SERVICE', {
sendEmail,
getUrl,
});
// find the handler using propertyName and replace it with apis you use in your resolver;
const handler = Container.handlers.find(handler => handler.propertyName === 'userRepository');
handler!.value = function () {
return {
create: saveMock,
save: createMock,
};
}
// use container to get resolver instance;
const resolver = Container.get(RegisterResolver);
// methods may use orm operations;
await resolver.register({
password: '123',
firstName: 'l',
lastName: 'dd',
email: 'ldd@163.com',
});
// mocked orm operation get called.
expect(saveMock).toHaveBeenCalled();
expect(createMock).toHaveBeenCalled();
});
}); this is a brief example and it satisfied my needs. |
Function // UserRepository.ts
import { EntityRepository, Repository } from 'typeorm';
@Service()
@EntityRepository(User)
export class UserRepository extends Repository<User> { } // UserResolver.ts
import { Service } from 'typedi';
import { InjectRepository } from 'typeorm-typedi-extensions';
@Service()
export class UserResolver {
@InjectRepository()
private readonly userRepository!: UserRepository;
} // UserResolver.test.ts
import { ConnectionManager } from 'typeorm';
// mocked repository
class MockUserRepository {
static findOne: jest.MockedFunction<typeof UserRepository.prototype.findOne>;
static setupMocks() {
this.findOne = jest.fn().mockResolvedValue(undefined);
}
}
describe('UserResolver class', () => {
beforeAll(() => {
// This, as we know, is not enough for mocking @InjectRepository()
// Container.set(UserRepository, MockUserRepository);
// this will be used only once during the initial import so there is no need to put this in beforeEach
Container.set(ConnectionManager, {
has: (connectionName: string) => true,
get: (connectionName: string) => ({
getRepository: (entityType: any) => {
console.warn(`No mock repository found for ${entityType}`);
},
getMongoRepository: (entityType: any) => {
console.warn(`No mock repository found for ${entityType}`);
},
getTreeRepository: (entityType: any) => {
console.warn(`No mock repository found for ${entityType}`);
},
getCustomRepository: (repositoryType: any) => {
switch (repositoryType) {
case UserRepository:
return MockUserRepository; // here we mock our repository
default:
console.warn(`No mock repository found for ${repositoryType}`);
}
},
}),
});
});
beforeEach(() => {
MockUserRepository.setupMocks();
});
it('should pass', async () => {
MockUserRepository.findOne.mockResolvedValue({});
await <test>
expect(MockUserRepository.findOne).toHaveBeenCalledWith({ email: '...' });
});
}); if you inject repository as: @InjectRepository(User)
private readonly userRepository!: Repository<User>; then this should work: Container.set(ConnectionManager, {
has: (connectionName: string) => true,
get: (connectionName: string) => ({
getRepository: (entityType: any) => {
switch (entityType) {
case User:
return mockUserRepository;
default:
console.warn(`No mock repository found for ${entityType}`);
}
},
}),
}); |
Closing as solved, as multiple solutions have been posted. |
InjectRepository
InjectRepository
?
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
I couldn't find any way to mock repositories injected by
InjectRepository
.Apparently
Container.set
is not the way to go.I ended up mocking the whole library for now
The text was updated successfully, but these errors were encountered: