Javascript 模拟依赖的构造函数 Jest

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47606545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:53:02  来源:igfitidea点击:

Mock a dependency's constructor Jest

javascriptnode.jsecmascript-6aws-sdkjestjs

提问by Oliver Shaw

I'm a newbie to Jest. I've managed to mock my own stuff, but seem to be stuck mocking a module. Specifically constructors.

我是 Jest 的新手。我设法模拟了我自己的东西,但似乎被困在模拟模块中。特别是构造函数。

usage.js

用法.js

const AWS = require("aws-sdk")
cw = new AWS.CloudWatch({apiVersion: "2010-08-01"})
...
function myMetrics(params) { 
  cw.putMetricData(params, function(err, data){})
}

I'd like to do something like this in the tests.

我想在测试中做这样的事情。

const AWS = jest.mock("aws-sdk")
class FakeMetrics {
  constructor() {}
  putMetricData(foo,callback) {
    callback(null, "yay!")
  }
}

AWS.CloudWatch = jest.fn( (props) => new FakeMetrics())

However when I come to use it in usage.jsthe cw is a mockConstructornot a FakeMetrics

然而,当我在usage.jscw 中使用它时,它mockConstructor不是一个FakeMetrics

I realise that my approach might be 'less than idiomatic' so I'd be greatful for any pointers.

我意识到我的方法可能“不太习惯”,所以我会很乐意提供任何指示。

This is a minimal example https://github.com/ollyjshaw/jest_constructor_so

这是一个最小的例子https://github.com/ollyjshaw/jest_constructor_so

npm install -g jest

npm install -g jest

jest

jest

采纳答案by Estus Flask

The problem is how a module is being mocked. As the referencestates,

问题是如何模拟模块。正如参考文献所述,

Mocks a module with an auto-mocked version when it is being required. <...> Returns the jest object for chaining.

在需要时使用自动模拟版本模拟模块。<...> 返回用于链接的 jest 对象。

AWSis not module object but jestobject, and assigning AWS.CloudFormationwill affect nothing.

AWS不是模块对象而是jest对象,赋值AWS.CloudFormation不会有任何影响。

Also, it's CloudWatchin one place and CloudFormationin another.

此外,它CloudWatch在一个地方和CloudFormation另一个地方。

Testing framework doesn't require to reinvent mock functions, they are already there. It should be something like:

测试框架不需要重新发明模拟函数,它们已经存在。它应该是这样的:

const AWS = require("aws-sdk");
const fakePutMetricData = jest.fn()
const FakeCloudWatch = jest.fn(() => ({
    putMetricData: fakePutMetricData
}));                        
AWS.CloudWatch = FakeCloudWatch;

And asserted like:

并断言:

expect(fakePutMetricData).toHaveBeenCalledTimes(1);

回答by kimy82

Above answer works. However, after some time working with jestI would just use the mockImplementationfunctionality which is useful for mocking constructors.

以上答案有效。但是,在使用jest一段时间后,我只会使用mockImplementation功能,这对于模拟构造函数很有用。

Below code could be an example:

下面的代码可以是一个例子:

import * as AWS from 'aws-sdk';

jest.mock('aws-sdk', ()=> {
    return {
        CloudWatch : jest.fn().mockImplementation(() => { return {} })
    }
});

test('AWS.CloudWatch is called', () => {
    new AWS.CloudWatch();
    expect(AWS.CloudWatch).toHaveBeenCalledTimes(1);
});

Note that in the example the new CloudWatch()just returns an empty object.

请注意,在示例中,new CloudWatch()仅返回一个空对象。

回答by David

According to the documentationmockImplementationcan also be used to mock class constructors:

根据文档mockImplementation还可以用于模拟类构造函数:

// SomeClass.js
module.exports = class SomeClass {
  method(a, b) {}
};

// OtherModule.test.js
jest.mock('./SomeClass'); // this happens automatically with automocking
const SomeClass = require('./SomeClass');
const mockMethod= jest.fn();
SomeClass.mockImplementation(() => {
  return {
    method: mockMethod,
  };
});

const some = new SomeClass();
some.method('a', 'b');
console.log('Calls to method: ', mockMethod.mock.calls);