如何使用Jest模拟ES6模块导入?

2020/10/05 02:01 · javascript ·  · 0评论

我想测试我的一个ES6模块调用特定方式的另一个ES6模块。有了茉莉花,这非常容易-

应用代码:

// myModule.js
import dependency from './dependency';

export default (x) => {
  dependency.doSomething(x * 2);
}

和测试代码:

//myModule-test.js
import myModule from '../myModule';
import dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    spyOn(dependency, 'doSomething');

    myModule(2);

    expect(dependency.doSomething).toHaveBeenCalledWith(4);
  });
});

笑话相当于什么?我觉得这是一件很想做的简单的事,但是我一直在努力尝试弄清头发。

我最接近的是将imports替换为requires,并将其移入测试/函数中。都不是我想做的事情。

// myModule.js
export default (x) => {
  const dependency = require('./dependency'); // Yuck
  dependency.doSomething(x * 2);
}

//myModule-test.js
describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    jest.mock('../dependency');

    myModule(2);

    const dependency = require('../dependency'); // Also yuck
    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

为了获得加分,我很想在其中的函数dependency.js为默认导出时使整个工作正常进行但是,我知道监视默认出口在Jasmine中不起作用(或者至少我永远无法使它起作用),所以我也不希望在Jest中也有可能。

我已经能够通过使用涉及到的hack来解决此问题import *它甚至适用于命名和默认导出!

对于命名出口:

// dependency.js
export const doSomething = (y) => console.log(y)

// myModule.js
import { doSomething } from './dependency';

export default (x) => {
  doSomething(x * 2);
}

// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    dependency.doSomething = jest.fn(); // Mutate the named export

    myModule(2);

    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

或默认导出:

// dependency.js
export default (y) => console.log(y)

// myModule.js
import dependency from './dependency'; // Note lack of curlies

export default (x) => {
  dependency(x * 2);
}

// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    dependency.default = jest.fn(); // Mutate the default export

    myModule(2);

    expect(dependency.default).toBeCalledWith(4); // Assert against the default
  });
});

正如Mihai Damian在下面正确指出的那样,这是对的模块对象进行了变异dependency,因此它将“泄漏”到其他测试中。因此,如果使用这种方法,则应存储原始值,然后在每次测试后再次将其重新设置。

要使用Jest轻松实现此目的,请使用spyOn()方法而不是jest.fn(),因为它支持轻松恢复其原始值,因此避免了前面提到的“泄漏”。

您必须模拟模块并自行设置间谍程序:

import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency', () => ({
  doSomething: jest.fn()
}))

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    myModule(2);
    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

要使用Jest模拟ES6依赖项模块的默认导出,请执行以下操作:

import myModule from '../myModule';
import dependency from '../dependency';

jest.mock('../dependency');

// If necessary, you can place a mock implementation like this:
dependency.mockImplementation(() => 42);

describe('myModule', () => {
  it('calls the dependency once with double the input', () => {
    myModule(2);

    expect(dependency).toHaveBeenCalledTimes(1);
    expect(dependency).toHaveBeenCalledWith(4);
  });
});

其他选项对我的情况不起作用。

Andreas的答案中添加更多内容我在ES6代码上遇到了同样的问题,但是我不想更改导入内容。看起来很黑。所以我这样做:

import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency');

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    myModule(2);
  });
});

而添加的文件dependency.js在“__的嘲笑__”并行文件夹dependency.js这对我有用。另外,这使我可以选择从模拟实现中返回合适的数据。确保为要模拟的模块提供正确的路径。

快速前进到2020年,我发现此博客文章是解决方案:Jest模拟默认值并命名为export

仅使用ES6模块语法:

// esModule.js
export default 'defaultExport';
export const namedExport = () => {};

// esModule.test.js
jest.mock('./esModule', () => ({
  __esModule: true, // this property makes it work
  default: 'mockedDefaultExport',
  namedExport: jest.fn(),
}));

import defaultExport, { namedExport } from './esModule';
defaultExport; // 'mockedDefaultExport'
namedExport; // mock function

您还需要知道的一件事(花了我一段时间才弄清楚)是,您不能在测试内调用jest.mock()。您必须在模块的顶层调用它。但是,如果要为不同的测试设置不同的模拟,则可以在各个测试中调用mockImplementation()。

该问题已得到解答,但是您可以这样解决:

文件dependency.js

const doSomething = (x) => x
export default doSomething;

档案myModule.js

import doSomething from "./dependency";

export default (x) => doSomething(x * 2);

文件myModule.spec.js

jest.mock('../dependency');
import doSomething from "../dependency";
import myModule from "../myModule";

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    doSomething.mockImplementation((x) => x * 10)

    myModule(2);

    expect(doSomething).toHaveBeenCalledWith(4);
    console.log(myModule(2)) // 40
  });
});

我用另一种方法解决了。假设您有dependency.js

export const myFunction = () => { }

除以下内容外,我还创建了一个depdency.mock.js文件:

export const mockFunction = jest.fn();

jest.mock('dependency.js', () => ({ myFunction: mockFunction }));

在测试中,在导入具有依赖性的文件之前,我使用:

import { mockFunction } from 'dependency.mock'
import functionThatCallsDep from './tested-code'

it('my test', () => {
    mockFunction.returnValue(false);

    functionThatCallsDep();

    expect(mockFunction).toHaveBeenCalled();

})
本文地址:http://javascript.askforanswer.com/ruheshiyongjestmonies6mokuaidaoru.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!