简体   繁体   English

NestJS 中使用 Mongoose 的测试服务

[英]Testing Service with Mongoose in NestJS

I am trying to test my LoggingService in NestJS and while I cannot see anything that is wrong with the test the error I am getting is Error: Cannot spy the save property because it is not a function; undefined given instead我正在尝试在 NestJS 中测试我的 LoggingService,虽然我看不到测试有任何问题,但我得到的错误是Error: Cannot spy the save property because it is not a function; undefined given instead Error: Cannot spy the save property because it is not a function; undefined given instead

The function being tested (trimmed for brevity):正在测试的 function(为简洁起见):

@Injectable()
export class LoggingService {
  constructor(
    @InjectModel(LOGGING_AUTH_MODEL) private readonly loggingAuthModel: Model<IOpenApiAuthLogDocument>,
    @InjectModel(LOGGING_EVENT_MODEL) private readonly loggingEventModel: Model<IOpenApiEventLogDocument>,
  ) {
  }
  
  async authLogging(req: Request, requestId: unknown, apiKey: string, statusCode: number, internalMsg: string) {
    
    const authLog: IOpenApiAuthLog = {
///
    }
    
    await new this.loggingAuthModel(authLog).save();
  }
}

This is pretty much my first NestJS test and as best I can tell this is the correct way to test it, considering the error is right at the end it seems about right.这几乎是我的第一次 NestJS 测试,而且我可以说这是测试它的正确方法,考虑到错误最终是正确的,它似乎是正确的。

describe('LoggingService', () => {
  let service: LoggingService;
  let mockLoggingAuthModel: IOpenApiAuthLogDocument;
  let request;
  
  beforeEach(async () => {
    request = new JestRequest();
    
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        LoggingService,
        {
          provide: getModelToken(LOGGING_AUTH_MODEL),
          useValue: MockLoggingAuthModel,
        },
        {
          provide: getModelToken(LOGGING_EVENT_MODEL),
          useValue: MockLoggingEventModel,
        },
      ],
    }).compile();
    
    service = module.get(LoggingService);
    mockLoggingAuthModel = module.get(getModelToken(LOGGING_AUTH_MODEL));
  });
  
  it('should be defined', () => {
    expect(service).toBeDefined();
  });
  
  it('authLogging', async () => {
    const reqId = 'mock-request-id';
    const mockApiKey = 'mock-api-key';
    const mockStatusCode = 200;
    const mockInternalMessage = 'mock-message';
    
    await service.authLogging(request, reqId, mockApiKey, mockStatusCode, mockInternalMessage);
    
    const authSpy = jest.spyOn(mockLoggingAuthModel, 'save');
    expect(authSpy).toBeCalled();
  });
});

The mock Model:模拟 Model:

class MockLoggingAuthModel {
  constructor() {
  }
  
  public async save(): Promise<void> {
  }
}

The issue comes from the fact that you pass a class to the TestingModule while telling it that it's a value.问题在于您将 class 传递给TestingModule ,同时告诉它它是一个值。

Use useClass to create the TestingModule :使用useClass创建TestingModule

beforeEach(async () => {
  request = new JestRequest();
  
  const module: TestingModule = await Test.createTestingModule({
    providers: [
      LoggingService,
      {
        provide: getModelToken(LOGGING_AUTH_MODEL),
        // Use useClass
        useClass: mockLoggingAuthModel,
      },
      {
        provide: getModelToken(LOGGING_EVENT_MODEL),
        // Use useClass
        useClass: MockLoggingEventModel,
      },
    ],
  }).compile();
  
  service = module.get(LoggingService);
  mockLoggingAuthModel = module.get(getModelToken(LOGGING_AUTH_MODEL));
});

After much more googling I managed to find this testing examples Repo: https://github.com/jmcdo29/testing-nestjs which includes samples on Mongo and also suggest that using the this.model(data) complicates testing and one should rather use `this.model.create(data).经过更多的谷歌搜索后,我设法找到了这个测试示例 Repo: https://github.com/jmcdo29/testing-nestjs ,其中包括 Mongo 上的示例,并且还建议使用this.model(data)使测试复杂化,应该使用`this.model.create(数据)。

After making that change the tests are working as expected.进行该更改后,测试按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM