使用JEST不按预期工作来覆盖存根函数的行为



我有一个测试类,用于测试Nest控制器类中各种HTTP方法的行为。我使用Jest手动模拟来存根服务类中各种函数的行为,这样我就不必依赖于实际的依赖项/服务,例如:雪花。我有一个顶层的jest.mock()定义如下,它初始化服务类的模拟版本,而不是实际的服务类。被模拟的服务类在mock中创建。与实际服务类相邻的文件夹。我在"错误场景"描述块中重新定义了一个模拟函数的行为,如下面的代码片段所示,以测试错误场景。测试场景:"抛出错误"失败,因为它仍然拾取默认的模拟行为。如有任何指示或帮助,不胜感激。

简而言之,我希望能够为相同模拟类的单个函数定义不同的模拟行为,用于各种测试场景。

感谢
jest.mock('@modules/shipment-summary/shipment-summary.service');
describe('ShipmentSummaryController', () => {
let shipmentSummaryController: ShipmentSummaryController;
let shipmentSummaryService: ShipmentSummaryService;
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
imports: [],
controllers: [ShipmentSummaryController],
providers: [ShipmentSummaryService],
}).compile();
shipmentSummaryController = moduleRef.get<ShipmentSummaryController>(
ShipmentSummaryController,
);
shipmentSummaryService = moduleRef.get<ShipmentSummaryService>(
ShipmentSummaryService,
);
jest.clearAllMocks();
});
//All the tests inside this describe block work as expected
describe('valid shipment-mode scenario', () => {
describe('valid shipment modes for tenant', () => {
let modes: ShipmentMode[];
beforeEach(async () => {
modes = await shipmentSummaryController.getAllShipmentModes('256');
});
test('calls the service fn. with the correct arg', () => {
expect(shipmentSummaryService.getAvailableShipmentModes).toBeCalledWith(
'256',
);
});
test('all available shipment modes for 256 are returned', () => {
expect(modes).toEqual(validModeDropdown());
});
});
});
// redefining behavior of getAllshipmentModes() is not working
describe('error scenario', () => {
let modes: ShipmentMode[] = []
beforeEach(async () => {
modes = await shipmentSummaryController.getAllShipmentModes('256');
});

beforeAll(() => {
jest.clearAllMocks();
jest.mock('@modules/shipment-summary/shipment-summary.service.ts', () => {
return {
getAvailableShipmentModes: () => {
throw new Error('Test error');
}, 
}  
});
});

test('throws an error', () => {
expect(() => shipmentSummaryController.getAllShipmentModes('256')).toThrow();
})
})
});

我的mock服务类如下:

export const ShipmentSummaryService = jest.fn().mockReturnValue({

// Fn. to be mocked differently per test scenario.
getAvailableShipmentModes: jest.fn().mockResolvedValue(validModeDropdown()),
});

有很多方法可以做到这一点。Nest文档概述了其中的一些。然而,我最喜欢的一种方式,useValue,并不是很清楚,所以我将在这里添加它。

本例中也会使用jest为了监视一个模拟,改变其行为取决于测试。

  1. 想象这两个简单的资源
Injectable();
export class SimpleService {
public sayHello(): string {
return "Hello, world!";
}
}
@Controller()
export class SimpleController {
constructor(
@Inject(SimpleService) private readonly simpleService: SimpleService
) {}
@Get()
public controllerSaysHello(): string {
return this.simpleService.sayHello();
}
}
  1. 您的测试可能看起来像这样
describe("SimpleController", () => {
let controller: SimpleController;
const mockReturnValue = "Goodbye, world..",
mockSimpleService: SimpleService = {
sayHello: () => mockReturnValue,
};
beforeEach(() => {
jest.restoreAllMocks();
});
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
SimpleController,
{ provide: SimpleService, useValue: mockSimpleService },
],
}).compile();
controller = module.get(SimpleController);
});
test("default mockSimpleService", () => {
const result = controller.controllerSaysHello();
expect(result).toBe(mockReturnValue);
});
test("spied on mockSimpleService", () => {
const differentReturnValue = "Hallo!";
jest
.spyOn(mockSimpleService, "sayHello")
.mockReturnValue(differentReturnValue);
const result = controller.controllerSaysHello();
expect(result).toBe(differentReturnValue);
});
});

最新更新