我正在尝试测试,在向我的一个控制器发送请求后,队列会推送作业。实现本身如预期的那样工作。
这是我的应用程序模块.ts
@Module({
imports: [
HttpModule,
TypeOrmModule.forRoot(typeOrmConfig),
BullModule.forRoot({
redis: {
host: redisConfig.host,
port: redisConfig.port,
},
}),
// Bunch of unrelated modules
],
providers: [
{
provide: APP_FILTER,
useClass: AllExceptionsFilter,
},
],
controllers: [SomeControllers],
})
export class AppModule {}
这就是我的import.module.ts(使用队列的模块(的样子:
@Module({
imports: [
BullModule.registerQueue({
name: importQueueName.value,
}),
//More unrelated modules,
],
providers: [
//More services, and bull consumer and producer,
ImportDataProducer,
ImportDataConsumer,
ImportDataService,
],
controllers: [ImportDataController],
})
export class ImportDataModule {}
我试着采用这种方法
它没有在beforeAll钩子中注册队列,我得到了
Driver not Connected
这种方法
它在测试套件的beforeAll钩子中注册了一个队列,我得到了:
TypeError: Cannot read properties of undefined (reading 'call')
at BullExplorer.handleProcessor (node_modules/@nestjs/bull/dist/bull.explorer.js:95:23)
at MapIterator.iteratee (node_modules/@nestjs/bull/dist/bull.explorer.js:59:26)
at MapIterator.next (node_modules/iterare/src/map.ts:9:39)
at FilterIterator.next (node_modules/iterare/src/filter.ts:11:34)
at IteratorWithOperators.next (node_modules/iterare/src/iterate.ts:19:28)
at Function.from (<anonymous>)
at IteratorWithOperators.toArray (node_modules/iterare/src/iterate.ts:227:22)
at MetadataScanner.scanFromPrototype (node_modules/@nestjs/core/metadata-scanner.js:12:14)
at node_modules/@nestjs/bull/dist/bull.explorer.js:56:34
at Array.forEach (<anonymous>)
这是我的"基本测试套件":
describe('Queue test suite', () => {
let app: INestApplication;
const importQueue: any = { add: jest.fn() };
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule, ImportDataModule],
})
.overrideProvider(importQueueName.value)
.useValue(importQueue)
.compile();
app = moduleFixture.createNestApplication();
app.useGlobalPipes(
new ValidationPipe({
transform: true,
whitelist: true,
forbidNonWhitelisted: true,
}),
);
await app.init();
});
afterAll(async () => {
await app.close();
});
test('A job should be pushed', async () => {
await request(app.getHttpServer())
.post('/some/route')
.attach('file', __dirname + '/some.file')
.expect(HttpStatus.CREATED);
expect(importQueue.add).toHaveBeenCalled();
});
});
知道这里可能出了什么问题吗?
我也遇到了同样的问题,问题出在您的mockQueue
上。您需要添加一个process
模拟函数。
这应该对你有用!
const importQueue: any = {
add: jest.fn(),
process: jest.fn(),
};
我就是这样测试的。
expect(mockQueue.add).toBeCalledTimes(1);
expect(mockQueue.add).nthCalledWith(
1,
PendoJobNames.SCR,
{
...mockJobDto,
},
{
jobId: mockDto.visitorId,
removeOnComplete: true,
removeOnFail: true,
},
);
```
我发现了一种简单的方法,可以使用包@golevelup/ts-jest
中的createMock
函数对类或接口进行深度模拟,该函数与NestJS依赖注入配合良好。
let someController: SomeController;
let someService: DeepMocked<SomeService>;
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
imports: [SomeModule],
controllers: [SomeController],
providers: [
{
provide: SomeService,
useValue: createMock<SomeService>(),
},
{ provide: getConnectionToken(), useValue: createMock<Connection>() },
{ provide: getQueueToken('queueName'), useValue: createMock<Queue>() },
],
}).compile();
someController = moduleRef.get<SomeController>(SomeController);
someService = moduleRef.get(SomeService);
});
import { createMock } from "@golevelup/ts-jest";
import { getQueueOptionsToken, getQueueToken } from "@nestjs/bullmq";
import { Test } from "@nestjs/testing";
import { Queue, QueueOptions } from "bullmq";
describe("SomeModule", () => {
let module: SomeModule;
beforeEach(async () => {
const testingModule = await Test.createTestingModule({
imports: [
/* ... */
],
})
.overrideProvider(getQueueOptionsToken())
.useValue(createMock<QueueOptions>())
.overrideProvider(getQueueToken("yourQueueName"))
.useValue(createMock<Queue>())
.compile();
module = testingModule.get(SomeModule);
});
it("can be instantiated by Nest", () => {
expect(module).toBeDefined();
});
});
@moogs的答案是正确的,但我还必须添加另一个函数。
const queueMock = {
add: jest.fn(),
process: jest.fn(),
on: jest.fn()
};
on
函数,并且它起作用了。