Javascript:使用 Sinon 模拟构造函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14569499/
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-24 17:14:14  来源:igfitidea点击:

Javascript: Mocking Constructor using Sinon

javascriptunit-testingconstructormockingsinon

提问by sevenstripe

I am pulling my hair out trying to figure out how to mock a constructor using sinon. I have a function that will create multiple widgets by calling a constructor that accepts a few arguments. I want to verify that the constructor is called the correct number of times with the correct parameters, but I don't want to actually construct the widgets. The following links seemingly explain a straightforward way of mocking the constructor, however it does not work for me:

我正在努力弄清楚如何使用 sinon 模拟构造函数。我有一个函数可以通过调用接受几个参数的构造函数来创建多个小部件。我想用正确的参数验证构造函数被调用的次数是否正确,但我不想实际构造小部件。以下链接似乎解释了一种模拟构造函数的简单方法,但它对我不起作用:

Spying on a constructor using Jasmine

使用 Jasmine 监视构造函数

http://tinnedfruit.com/2011/03/25/testing-backbone-apps-with-jasmine-sinon-2.html

http://tinnedfruit.com/2011/03/25/testing-backbone-apps-with-jasmine-sinon-2.html

When I make the following call to stub the constructor:

当我进行以下调用来存根构造函数时:

sinon.stub(window, "MyWidget");

I get the following error:

我收到以下错误:

Uncaught TypeError: Attempted to wrap undefined property MyWidget as function 

When debugging in Chrome I see MyWidget shows up in the Local section of the Scope Variables, however there is not MyWidget property off of window.

在 Chrome 中调试时,我看到 MyWidget 显示在范围变量的本地部分,但是窗口外没有 MyWidget 属性。

Any help would be greatly appreciated.

任何帮助将不胜感激。

采纳答案by sevenstripe

I was able to get StubModuleto work after a few tweaks, most notably passing in async:false as part of the config when requiring in the stubbed module.

经过一些调整后,我能够让StubModule工作,最显着的是在存根模块中需要时传入 async:false 作为配置的一部分。

Kudos to Mr. Davis for putting that together

感谢戴维斯先生把这些放在一起

回答by starmer

I needed a solution for this because my code was calling the new operator. I wanted to mock the object that the new call created.

我需要一个解决方案,因为我的代码正在调用 new 运算符。我想模拟新调用创建的对象。

var MockExample = sinon.stub();
MockExample.prototype.test = sinon.stub().returns("42");
var example = new MockExample();
console.log("example: " + example.test()); // outputs 42

Then I used rewire to inject it into the code that I was testing

然后我使用 rewire 将其注入到我正在测试的代码中

rewiredModule = rewire('/path/to/module.js');
rewiredModule.__set__("Example", example);

回答by ppoliani

From the official site of sinonjs:

来自sinonjs的官方网站:

Replaces object.method with a stub function. The original function can be restored bycalling object.method.restore(); (or stub.restore();). An exception is thrown if the property is not >already a function, to help avoid typos when stubbing methods.

用存根函数替换 object.method。可以通过调用 object.method.restore() 恢复原函数;(或 stub.restore();)。如果属性不是>已经是函数,则会引发异常,以帮助避免在存根方法时出现拼写错误。

this simply states that the function for which you want to create the stub must be member of the objectobject.

这只是说明要为其创建存根的函数必须是对象对象的成员。

To make things clear; you call

把事情说清楚;你打电话

sinon.stub(window, "MyWidget");

The MyWidget function needs to be within the global scope (since you pass windowas parameter). However, as you already said, this function is in a local scope (probably defined within an object literal or a namespace).

MyWidget 函数需要在全局范围内(因为您将window作为参数传递)。但是,正如您已经说过的,此函数在本地范围内(可能在对象文字或命名空间中定义)。

In javascript everyone can have access to the global scope, but not the other way around.

在 javascript 中,每个人都可以访问全局范围,但反过来不行。

Check where you declare the MyWidget function and pass container object as first parameter to sinon.stub()

检查在何处声明 MyWidget 函数并将容器对象作为第一个参数传递给 sinon.stub()

回答by theUtherSide

Using Sinon 4.4.2, I was able to mock an instance method like this:

使用 Sinon 4.4.2,我能够模拟这样的实例方法:

const testObj = { /* any object */ }
sinon.stub(MyClass.prototype, "myMethod").resolves(testObj)
let myVar = await new MyClass(token).myMethod(arg1, arg2)
// myVar === testObj

A similar solution provided here: Stubbing a class method with Sinon.js

这里提供了一个类似的解决方案: Stubbing a class method with Sinon.js

回答by user3331119

I used Mockery to Mock a Constructor/Function without any problems.

我使用 Mockery 模拟构造函数/函数没有任何问题。

var mockery = require('mockery');
var sinon = require('sinon');

mockery.enable({
  useCleanCache: true,
  warnOnReplace: false,
  warnOnUnregistered: false
});

exports.Client = function() {/* Client constructor Mock */};
var ClientSpy = sinon.spy(exports, 'Client');
mockery.registerMock('Client', ClientSpy);

var Factory = require('Factory'); // this module requires the Client module

You should be able to apply a Sinon Spy just as the example above does.

您应该能够像上面的示例一样应用 Sinon Spy。

Make sure to disable or reset Mockery after the test(s)!

确保在测试后禁用或重置 Mockery!

回答by AXMIM

Just found this in the documentation.

刚刚在文档中找到了这个

If you want to create a stub object of MyConstructor, but don't want the constructor to be invoked, use this utility function.

var stub = sinon.createStubInstance(MyConstructor)

如果要创建 MyConstructor 的存根对象,但不想调用构造函数,请使用此实用程序函数。

var stub = sinon.createStubInstance(MyConstructor)

回答by Yiling

Use sinon.createStubInstance(MyES6ClassName), then when MyES6ClassName is called with a newkeyword, a stub of MyES6ClassName instance will returned.

使用sinon.createStubInstance(MyES6ClassName),然后当 MyES6ClassName 使用new关键字调用时,将返回 MyES6ClassName 实例的存根。

回答by user1978019

I ran into this error by mistakenly typing sinon.stub.throws(expectedErr)rather than sinon.stub().throws(expectedErr). I've made similar mistakes before and not encountered this particular message before, so it threw me.

我错误地输入sinon.stub.throws(expectedErr)而不是sinon.stub().throws(expectedErr). 我以前也犯过类似的错误,之前没有遇到过这个特定的消息,所以它把我扔了。