6

我对如何在浏览器中全局模拟文件选择器感兴趣。具体来说,我最感兴趣的是在Firefox中执行此操作,但更喜欢通用解决方案。

我只关心防止文件选择器对话框出现。我不需要能够断言它确实打开了。问题是我对打开文件选择器的 JavaScript 代码进行了单元测试。当对话框打开时,它会停止执行测试套件

一个示例情况是我正在测试onRender. Backbone.View该方法呈现一个子视图,该子视图将在呈现时打开文件选择器。由于我不直接测试该子视图,因此当我只对方法的其他部分进行单元测试感兴趣时,我不希望模拟它的部分行为onRender

例子:

//Test file
it("should do something", function() {
  var view = new App.Views.SomeView();
  spyOn(view.modelBinder, "bind");
  view.render();
  expect(view.modelBinder.bind).toHaveBeenCalled();
});

//View file
onRender : function () {
  this.modelBinder.bind(this.el, this.model);
  this.$("#thing").html(this.subview.render().el); //This line has a side effect that opens file picker
}

本质上,我不想明确地模拟导致文件选择器打开的行为,因为这不是我在这里测试的兴趣所在。这样做会使测试套件变得更加脆弱和难以维护。

4

2 回答 2

1

使用sinon来模拟/监视/存根调用。您可以测试正在拨打的电话,而不是实际拨打电话。

这样您就可以测试该函数是否已被调用,而无需调用显示对话框的实际函数。

于 2012-11-20T20:19:23.467 回答
0

回答你的问题:不要。

我会subview.render()用一个空函数替换以避免不希望的副作用。然而你说:

“我不想明确地模拟导致文件选择器打开的行为,因为这不是我感兴趣的测试......”

这有点矛盾。如果你想进行单元测试App.Views.SomeView,你不得不模拟外部协作者,特别是在不感兴趣的时候,包括你的文件选择器。另一方面,在对SUT进行单元测试时,您不应该弄乱它。

模拟实际上会使您的测试更容易出现红色,但这是确保您的生产代码不会遭受不良耦合形式的唯一方法(恕我直言,Backbone.js 应用程序的常见陷阱。)

唯一需要避免显示文件选择器的地方是对文件选择器本身进行单元测试时,在这种情况下,您可以按照建议使用 sinon,或者如果您使用的是 jQuery,则不覆盖它。记住“永远不要模拟你不拥有的类型”规则。

于 2013-01-08T18:52:40.540 回答