【问题标题】:Mock method from class 'b' that is called in class 'a'在类“a”中调用的“b”类的模拟方法
【发布时间】:2021-08-05 12:40:10
【问题描述】:

我正在尝试测试 test.controller.ts 类中的一个方法,该方法也恰好调用了另一个正在单独测试的类中的方法,所以我想模拟该调用。

这是一个示例设置,以显示我正在尝试做的事情。

TestController.test.ts

import {TestController} from "../../src/controllers/test.controller";
import {TestService} from "../../src/services/test.service";

describe("Test TestController", () => {

    test("exampleController", () => {

        jest.mock('../../src/services/test.service');
        let testService = new TestService();
        let testController = new TestController();

        // Mock testService.exampleService so it returns 2.

        let result = testController.exampleController();
        expect(result).resolves.toBe(2);
    });

});

test.controller.ts

import {TestService} from "../services/test.service";

export class TestController {
    private testService: TestService;

    constructor() {
        this.testService = new TestService();
    }

    public async exampleController() {
        return await this.testService.exampleService();
    }
}

test.service.ts

export class TestService {
    public async exampleService() {
        return 1;
    }
}

如何模拟“exampleService”方法,以便从 test.controller.ts 对“exampleController”方法的调用使用此模拟版本?

【问题讨论】:

    标签: javascript node.js typescript jestjs ts-jest


    【解决方案1】:

    您需要模拟 TestController 类的 testService 字段。 但是使用您当前的代码,这是不可能的,因为它是私人成员。
    这就是为什么首选使用依赖注入的原因,所以我们需要把你的构造函数改成这个,

      constructor(testService: TestService) {
            this.testService = testService;
        }
    

    我们现在传递TestService 的对象,而不是在构造函数中实例化 testService,以便于模拟。

    然后你就可以这样测试了,

    import {TestController} from "./controller";
    import {TestService} from "./service";
    
    jest.mock('./service.ts')
    
    describe("Test TestController", () => {
    
        test("exampleController", async () => {
           
            let testService = new TestService();
            jest.spyOn(testService, 'exampleService').mockResolvedValue(2)
    
            let testController = new TestController(testService);
    
            let result = await testController.exampleController();
           
            expect(result).toBe(2);
        });
    
    });
    

    在这里创建TestService 的对象。
    然后在testService 对象的exampleService 方法上创建一个间谍并模拟其解析值以返回2。
    然后将其传递给 TestController 的构造函数,这称为依赖注入,这样更容易测试。
    然后根据您的期望继续断言。

    【讨论】:

      【解决方案2】:

      如果您需要指定返回值并完全用模拟函数替换函数的实现,可以通过模拟函数上的jest.fnmockImplementationOnce 方法来完成。

      TestController.test.ts 应该是这样的

      import {TestController} from "../../src/controllers/test.controller";
      import {TestService} from "../../src/services/test.service";
      
      describe("Test TestController", () => {
          test("exampleController", () => {
              jest.mock('../../src/services/test.service');
              let testService = new TestService();
              let testController = new TestController();
      
              // Mock testService.exampleService so it returns 2.
              testService.exampleService = jest.fn().mockImplementationOnce(() => Promise.resolve(2));
      
              let result = testController.exampleController();
              expect(result).resolves.toBe(2);
          });
      
      });
      

      【讨论】:

        【解决方案3】:

        对于模拟函数,您可以使用sinon 库。如下图所示:

        let testService = new TestService();
              sinon.stub(testService, "exampleService").callsFake(function fakeFn() {
                        return 2;
             });
        

        【讨论】:

        • 我知道 Jest 确实内置了模拟功能,所以我真的希望只使用内置功能。
        猜你喜欢
        • 2013-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-21
        • 2020-06-08
        • 2022-06-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多