【问题标题】:Jest spyOn a function not Class or Object typeJest spyOn 不是类或对象类型的函数
【发布时间】:2018-09-02 14:10:08
【问题描述】:

我熟悉在类或对象方法上设置间谍,但是当函数只是一个导出默认值时怎么办 - 这样方法本身是独立的,就像一个实用程序一样?

我有一些像这样的现有代码:

const Funct1 = props => {
  if(props){
    Funct2(args);
  }
  // or return something
};
const Funct2 = props => {
  // do something
  return true
};
export default Funct1;  //Yes the existing export is named the same as the "entry" method above.

例如,我想监视Funct1 被调用,Funct2 返回 true。

import Funct1 from "../../../src/components/Funct1";
describe("Test the Thing", () => {
    it("New Test", () => {
        let props = {
            active: true,
            agentStatus: "online"
        };
        const spy = spyOn(Funct2, "method name"); <-- how doe this work if not an obj or class?

        Funct1(props);
        //If I try Funct2(props) instead, terminal output is "Funct2 is not defined"

        expect(spy).toHaveBeenCalledWith(props);
    });
});

【问题讨论】:

  • 我注意到这没有被接受的答案。仅供参考,我尝试import * as functions,然后创建一个const spy = jest.spyOn(functions, 'name')——但这对我不起作用。

标签: javascript jasmine jestjs


【解决方案1】:

我认为在不修改现有代码的情况下无法测试 Funct1 调用 Funct2。如果后者是一个选项,这里有两个选项来引入依赖注入:

  • 创建和导出工厂函数:

    const Funct2 = props => {
        // do something
        return true;
    };
    const Funct1 = CreateFunct1(Funct2);
    export function CreateFunct1(Funct2) {
        return props => {
            if (props) {
                Funct2(props);
            }
            // or return something
        };
    }
    export default Funct1;  
    
    // and here is the test:
    
    describe('Test the Thing', () => {
        it('New Test', () => {
            // Arrange
            const funct2Spy = jasmine.createSpy('Funct2');
            const funct1 = CreateFunct1(funct2Spy);
            const props = "some data";
    
            // Act
            funct1(props);
    
            // Assert
            expect(funct2Spy).toHaveBeenCalledWith(props);
        });
    });
    
  • 也导出 Funct2。这是关于此主题的thread。由于导出语法,它的示例可能需要针对您的场景进行一些调整。

【讨论】:

  • 问题是开玩笑而不是茉莉花
【解决方案2】:

我不是开玩笑的专家,但我的建议是:

1) 当函数默认导出时,我使用类似:

import Funct1 from "../../../src/components/Funct1";
...
jest.mock("../../../src/components/Funct1");
...
expect(Funct1).toHaveBeenCalledWith(params);

2) 当模块(utils.js)有多个导出为时

export const f1 = () => {};
...
export const f8 = () => {};

你可以试试

import * as Utils from "../../../src/components/utils"
const f8Spy = jest.spyOn(Utils, 'f8');
...
expect(f8Spy).toHaveBeenCalledWith(params);

Similar discussion here

【讨论】:

【解决方案3】:

我认为 Jest 需要在 Object 或 Class 中使用 mock,但如果它们在您的代码中不是这样,您仍然可以将它们放在测试中:

jest.mock('../pathToUtils', () => ({
  func2: jest.fun().mockImplementation((props) => "ok") //return what you want
  otherfuncs: ...etc
}));

const mockUtils = require('../pathToUtils')
const func1 = require('./pathToFunc1')

然后在测试中:

func1()  // call the main function

expect(mockUtils.func2).toHaveBeenCalled
expect(mockUtils.func2).toHaveBeenCalledTimes(1)
expect(mockUtils.func2).toHaveBeenCalledWith(arg1, arg2, etc)
expect(mockUtils.func2).toHaveBeenLastCalledWith(arg1, arg2, etc)

您已经在另一个文件中对 Util 函数进行了单元测试,因此您实际上不会在这里再次运行该函数,这只是为了集成测试的目的而模拟。

【讨论】:

    【解决方案4】:

    jest.fn 包装你的函数。像这样:

    const simpleFn = (arg) => arg;
    const simpleFnSpy = jest.fn(simpleFn);
    simpleFnSpy(1);
    expect(simpleFnSpy).toBeCalledWith(1); // Passes test
    

    【讨论】:

      猜你喜欢
      • 2017-11-29
      • 2015-01-25
      • 2012-06-22
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-05
      相关资源
      最近更新 更多