4

我有使用延迟对象的代码,该对象立即从对 $.ajax 的调用中返回。我需要为此代码编写单元测试,所以我不想实际往返服务器。

我可以存根 jQuery 并告诉存根返回我用于测试的 JSON,但这会破坏代码,因为它需要一个最终通过 JSON 响应解决的延迟对象,而不是直接的 JSON 响应。

我的解决方案尝试是存根 $.ajax 并告诉它返回一个立即执行的函数。在这个 IEFE 中,我创建了一个新的 $.Deferred 并设置了几毫秒的超时。超时后,我用我想要的 JSON 解析 $.Deferred。代码如下所示:

  stubbedAjax = sinon.stub jQuery, 'ajax'

  stubbedAjax.returns ( ->
    deferred = jQuery.Deferred()
    setTimeout ->
      deferred.resolve(JSON.stringify(customActionResponse))
    , 10
    return deferred
  )()

(这个咖啡脚本评估为以下 JS:)

var stubbedAjax;

stubbedAjax = sinon.stub(jQuery, 'ajax');

stubbedAjax.returns((function() {
  var deferred;
  deferred = jQuery.Deferred();
  setTimeout(function() {
    return deferred.resolve(JSON.stringify(customActionResponse));
  }, 10);
  return deferred;
})());

当我运行我的测试(使用 mocha 和 testem)时,我收到以下错误:

Uncaught TypeError: Cannot call method 'resolve' of undefined

我不明白为什么。引用是在函数定义时创建的。setTimeout 是在创建延迟对象的范围内定义的,因此它可以访问它。在 setTimeout 中放置一些 console.log 清楚地表明延迟对象已正确创建且可访问。

有谁知道为什么它说 deferred 是未定义的?或者可能是如何存根 jQuery ajax 响应同时仍使其立即返回延迟对象的替代解决方案?

提前致谢。

4

1 回答 1

2

无法发现代码中的错误,如果这个简单的小提琴表明它应该可以工作。

但是在 sinon 中有一个比 stubbing 更简单的方法$.ajax。只用假服务器

于 2013-08-21T15:15:13.967 回答