gpt4 book ai didi

javascript - 在 sinon 中 stub 整个类以进行测试

转载 作者:IT老高 更新时间:2023-10-28 23:10:49 26 4
gpt4 key购买 nike

序言:我已经阅读了很多 SO 和博客文章,但没有看到任何可以回答这个特定问题的内容。也许我只是在寻找错误的东西......

假设我正在开发一个 WidgetManager 类,它将对 Widget 对象进行操作。

如何使用 sinon 来测试 WidgetManager 是否正确使用了 Widget API,而不需要拉入整个 Widget 库?

基本原理:WidgetManager 的测试应该与 Widget 类分离。也许我还没有写 Widget,或者 Widget 是一个外部库。无论哪种方式,我都应该能够测试 WidgetManager 是否正确使用了 Widget 的 API,而无需创建真正的 Widget。

我知道 sinon 模拟只能在现有类上工作,据我所知,sinon stub 还需要类存在才能被 stub 。

具体来说,我将如何测试 Widget.create() 在以下代码中使用单个参数 'name' 仅被调用一次?

待测代码

// file: widget-manager.js

function WidgetManager() {
this.widgets = []
}

WidgetManager.prototype.addWidget = function(name) {
this.widgets.push(Widget.create(name));
}

测试代码

// file: widget-manager-test.js

var WidgetManager = require('../lib/widget-manager.js')
var sinon = require('sinon');

describe('WidgetManager', function() {
describe('#addWidget', function() {
it('should call Widget.create with the correct name', function() {
var widget_manager = new WidgetManager();
// what goes here?
});

it('should push one widget onto the widgets list', function() {
var widget_manager = new WidgetManager();
// what setup goes here?
widget_manager.addWidget('fred');
expect(widget_manager.widgets.length).to.equal(1);
});
});

旁白:当然,我可以定义一个 MockWidget 类来使用适当的方法进行测试,但我更感兴趣的是真正学习如何使用 sinon 的 spy/stub/mock 设施正确。

最佳答案

答案实际上与依赖注入(inject)有关。

您想测试 WidgetManager 是否以预期的方式与 dependency (Widget) 交互 - 并且您希望自由地操作和询问那个依赖。为此,您需要在测试时注入(inject) Widget 的 stub 版本。

根据 WidgetManager 的创建方式,有多个依赖注入(inject)选项。

一个简单的方法是让Widget依赖注入(inject)到WidgetManager构造函数中:

// file: widget-manager.js

function WidgetManager(Widget) {
this.Widget = Widget;
this.widgets = [];
}

WidgetManager.prototype.addWidget = function(name) {
this.widgets.push(this.Widget.create(name));
}

然后在您的测试中,您只需将一个 stub Widget 传递给被测 WidgetManager:

it('should call Widget.create with the correct name', function() {
var stubbedWidget = {
create: sinon.stub()
}
var widget_manager = new WidgetManager(stubbedWidget);
widget_manager.addWidget('fred');
expect(stubbedWidget.create.calledOnce);
expect(stubbedWidget.create.args[0] === 'fred');
});

您可以根据特定测试的需要修改 stub 的行为。例如,要测试小部件列表长度在小部件创建后是否增加,您可以简单地从您的 stub create() 方法返回一个对象:

  var stubbedWidget = {
create: sinon.stub().returns({})
}

这允许您完全控制依赖项,而无需模拟或 stub 所有方法,并允许您测试与其 API 的交互。

还有 proxyquire 等选项或 rewire这为在测试时覆盖依赖项提供了更强大的选项。最合适的选项取决于实现和偏好 - 但在所有情况下,您的目标只是在测试时替换给定的依赖项。

关于javascript - 在 sinon 中 stub 整个类以进行测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35737087/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com