我应该对$ .ajax的电话进行单元测试,还是已经发送了XHR?

时间:2014-02-27 18:43:53

标签: javascript unit-testing

假设我有以下方法:

function sendUserDataToServer(userData) {
    // Do some configuration stuff
    $.ajax('SomeEndpoint', userData);
}

为此函数编写单元测试时,我可以采用以下两种方法之一:

  1. $.ajax周围创建一个间谍,并检查是否使用预期参数调用了它。不会发送实际的XHR请求。
  2. 使用像SinonJs这样的库拦截ajax请求,并检查XHR对象以确保它已正确配置。
  3. 为什么我可以使用选项1:它将$ .ajax的功能与我的代码分开。如果由于jQuery中的错误导致$.ajax中断,则不会在我的单元测试结果中创建假阴性。

    为什么我可以使用选项2:如果我决定使用除jQuery之外的其他库来发送XHR,我将不必更改单元测试以检查其他方法。但是,如果该库中存在错误,我的单元测试将失败,我不一定知道它是库,而不是我的实际代码。

    哪种方法是正确的?

4 个答案:

答案 0 :(得分:4)

你的第一个选择是正确的。单元测试的目的是双重的

  • 验证您的代码合同
  • 验证它与其使用的其他内容进行通信。

您的问题是与$.ajax的互动,因此此测试的目的是确认它可以与其协作者正确对话。

如果你选择选项1,这正是你正在做的事情。如果选择选项2,则表示您正在测试第三方库,而不是正确执行通信协议。

你应该做两个测试。第二个测试可能足够快,可以与您的单元测试一起使用,即使有些人可能称之为集成测试。此测试告诉您正确使用库创建您要创建的对象。两者都可以让你区分代码中的错误和库,如果存在导致系统中其他东西失败的库错误,这将会派上用场。

答案 1 :(得分:0)

我的观点:选项1在单元测试中更正确。

单元测试应仅测试代码单元。在您的情况下,这将是您控制下的JavaScript(例如,函数内的逻辑,类或命名空间内的逻辑,具体取决于函数的上下文)。

您的单元测试应该模拟jQuery调用并相信它可以正常工作。做真正的AJAX调用很好,但这些都是集成测试的一部分。

请参阅this answer,了解什么是单位测试,什么不是单元测试。

顺便说一下,第三种方法是通过自定义代理类进行AJAX调用,可以在测试中进行模拟,但也可以切换你使用的库。

答案 2 :(得分:0)

我会使用选项1,但选择最容易理解的选项。

您在代码中依赖于jQuery,因此您无需担心它实际上正如您指出的那样工作。我发现,当您指定参数和响应并让代码处理它时,它会使测试更清晰。您还可以轻松指定应使用哪个回调(successerror)。

至于从jQuery更改库。如果更改代码,则测试应该失败。你可以说你的行为现在不同了。是的,您正在进行Ajax调用但具有不同的依赖性。并且应该更新您的测试以反映这一变化。

这两种方法都是正确的。如果要创建自己的发送Ajax调用的包装器,拦截XHR请求或手动创建请求并自行发送请求可能是有意义的。选择使您的测试最容易理解和维护的选项。

答案 3 :(得分:0)

最重要的是测试自己的代码。将业务逻辑与IO代码和业务逻辑分开。之后你应该有没有任何逻辑的方法来执行实际的IO(完全如你的例子)。而现在:你应该测试那种方法吗?这取决于。测试是为了让你感觉更安全。

  • 如果你真的担心jQuery会失败,你不能承受这种不太可能的情况而不是测试它。但不是使用一些模拟库,而是进行完整的端到端集成测试
  • 如果你不确定你是否正确使用jQuery,那么就进行'学习测试'。将参数传递给它并检查它产生的请求类型。在这种情况下,模拟测试应该足够了
  • 如果您需要前端和后端之间的合同文档,那么您可以选择是否要测试后端是否符合合同,前端或两者
  • 但如果以上都不适用于您,那么测试外部的,完善的框架是不是浪费时间? jquery家伙肯定已经测试过了。仍然你可能需要某种集成测试(自动或手动)来检查你的前端是否正确地与后端交互。那些测试将涵盖网络层