假设我有以下方法:
function sendUserDataToServer(userData) {
// Do some configuration stuff
$.ajax('SomeEndpoint', userData);
}
为此函数编写单元测试时,我可以采用以下两种方法之一:
$.ajax
周围创建一个间谍,并检查是否使用预期参数调用了它。不会发送实际的XHR请求。为什么我可以使用选项1:它将$ .ajax的功能与我的代码分开。如果由于jQuery中的错误导致$.ajax
中断,则不会在我的单元测试结果中创建假阴性。
为什么我可以使用选项2:如果我决定使用除jQuery之外的其他库来发送XHR,我将不必更改单元测试以检查其他方法。但是,如果该库中存在错误,我的单元测试将失败,我不一定知道它是库,而不是我的实际代码。
哪种方法是正确的?
答案 0 :(得分:4)
你的第一个选择是正确的。单元测试的目的是双重的
您的问题是与$.ajax
的互动,因此此测试的目的是确认它可以与其协作者正确对话。
如果你选择选项1,这正是你正在做的事情。如果选择选项2,则表示您正在测试第三方库,而不是正确执行通信协议。
你应该做两个测试。第二个测试可能足够快,可以与您的单元测试一起使用,即使有些人可能称之为集成测试。此测试告诉您正确使用库创建您要创建的对象。两者都可以让你区分代码中的错误和库,如果存在导致系统中其他东西失败的库错误,这将会派上用场。
答案 1 :(得分:0)
我的观点:选项1在单元测试中更正确。
单元测试应仅测试代码单元。在您的情况下,这将是您控制下的JavaScript(例如,函数内的逻辑,类或命名空间内的逻辑,具体取决于函数的上下文)。
您的单元测试应该模拟jQuery调用并相信它可以正常工作。做真正的AJAX调用很好,但这些都是集成测试的一部分。
请参阅this answer,了解什么是单位测试,什么不是单元测试。
顺便说一下,第三种方法是通过自定义代理类进行AJAX调用,可以在测试中进行模拟,但也可以切换你使用的库。
答案 2 :(得分:0)
我会使用选项1,但选择最容易理解的选项。
您在代码中依赖于jQuery,因此您无需担心它实际上正如您指出的那样工作。我发现,当您指定参数和响应并让代码处理它时,它会使测试更清晰。您还可以轻松指定应使用哪个回调(success
或error
)。
至于从jQuery更改库。如果更改代码,则测试应该失败。你可以说你的行为现在不同了。是的,您正在进行Ajax调用但具有不同的依赖性。并且应该更新您的测试以反映这一变化。
这两种方法都是正确的。如果要创建自己的发送Ajax调用的包装器,拦截XHR请求或手动创建请求并自行发送请求可能是有意义的。选择使您的测试最容易理解和维护的选项。
答案 3 :(得分:0)
最重要的是测试自己的代码。将业务逻辑与IO代码和业务逻辑分开。之后你应该有没有任何逻辑的方法来执行实际的IO(完全如你的例子)。而现在:你应该测试那种方法吗?这取决于。测试是为了让你感觉更安全。