Jest.js 如何在服务构造函数中对Controller进行单元测试并模拟@InjectModel

qqrboqgw  于 2022-12-16  发布在  Jest
关注(0)|答案(3)|浏览(199)

我在单元测试我的控制器时遇到问题,并收到错误“Nest无法解析我的服务的依赖项”。
为了最大限度的覆盖,我想对控制器和相应的服务进行单元测试,并模拟外部依赖,如mongoose连接。同样,我已经尝试了下面链接中提到的建议,但没有找到任何运气:
https://github.com/nestjs/nest/issues/194#issuecomment-342219043
请在下面找到我的代码:

export const deviceProviders = [
    {
        provide: 'devices',
        useFactory: (connection: Connection) => connection.model('devices', DeviceSchema),
        inject: ['DbConnectionToken'],
    },
];

export class DeviceService extends BaseService {
    constructor(@InjectModel('devices') private readonly _deviceModel: Model<Device>) {
        super();
    }

    async getDevices(group): Promise<any> {
        try {
            return await this._deviceModel.find({ Group: group }).exec();
        } catch (error) {
            return Promise.reject(error);
        }
    }
}

@Controller()
export class DeviceController {
    constructor(private readonly deviceService: DeviceService) {
    }

   @Get(':group')
   async getDevices(@Res() response, @Param('group') group): Promise<any> {
        try {
            const result = await this.deviceService.getDevices(group);
            return response.send(result);
        }
        catch (err) {
            return response.status(422).send(err);
        }
    }
}

@Module({
    imports: [MongooseModule.forFeature([{ name: 'devices', schema: DeviceSchema }])],
    controllers: [DeviceController],
    components: [DeviceService, ...deviceProviders],
})
export class DeviceModule { }

单元测试:

describe('DeviceController', () => {
    let deviceController: DeviceController;
    let deviceService: DeviceService;

    const response = {
        send: (body?: any) => { },
        status: (code: number) => response,
    };

    beforeEach(async () => {
        const module = await Test.createTestingModule({
            controllers: [DeviceController],
            components: [DeviceService, ...deviceProviders],
        }).compile();

        deviceService = module.get<DeviceService>(DeviceService);
        deviceController = module.get<DeviceController>(DeviceController);
    });

    describe('getDevices()', () => {
        it('should return an array of devices', async () => {
            const result = [{
                Group: 'group_abc',
                DeviceId: 'device_abc',
            },
            {
                Group: 'group_xyz',
                DeviceId: 'device_xyz',
            }];
            jest.spyOn(deviceService, 'getDevices').mockImplementation(() => result);

            expect(await deviceController.getDevices(response, null)).toBe(result);
        });
    });
});

当我运行上面的测试用例时,我得到了两个错误:
Nest无法解析DeviceService(?)的依赖项。请确保索引[0]处的参数在当前上下文中可用。
无法对基元值执行spyOn;未定义给定

qxgroojn

qxgroojn1#

示例代码:

import { Test } from '@nestjs/testing';

import { getModelToken } from '@nestjs/mongoose';

describe('auth', () => {
  let deviceController: DeviceController;
  let deviceService: DeviceService;

  const mockRepository = {
    find() {
      return {};
    }
  };

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [DeviceModule]
    })
      .overrideProvider(getModelToken('Auth'))
      .useValue(mockRepository)
      .compile();

    deviceService = module.get<DeviceService>(DeviceService);
  });

  // ...

});
mwkjh3gx

mwkjh3gx2#

你没有在这里注入正确的标记。你必须使用函数getModelToken来代替普通字符串。

import { getModelToken } from '@nestjs/mongoose';

// ...

{ provide: getModelToken('devices'), useFactory: myFactory },

字符串

ycl3bljg

ycl3bljg3#

下面是repo提供的解决方案。请参阅mongo-sample。我正在使用@injectModel和另一个服务测试我的API。下面是代码片段:

import { CategoriesService } from './../categories/categories.service';
import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import { ProductsService } from './products.service';

describe('ProductsService', () => {
  let service: ProductsService;

  beforeAll(async () => {
    const module: TestingModule = await Test.createTestingModule({
      // getModelToken to mock the MongoDB connection
      providers: [
        ProductsService,
        CategoriesService,
        {
          provide: getModelToken('Product'),
          useValue: {
            find: jest.fn(),
            findOne: jest.fn(),
            findByIdAndUpdate: jest.fn(),
            findByIdAndRemove: jest.fn(),
            save: jest.fn(),
          },
        },
        {
          provide: getModelToken('Category'),
          useValue: {
            find: jest.fn(),
            findOne: jest.fn(),
            findByIdAndUpdate: jest.fn(),
            findByIdAndRemove: jest.fn(),
            save: jest.fn(),
          },
        },
      ],
    }).compile();

    service = module.get<ProductsService>(ProductsService);
  });
  // your test case
});

相关问题