我对 Javacript 单元测试很陌生。一件事一直困扰着我。在测试 javascript 时,我们经常需要进行 DOM 操作。看起来我正在对控制器/组件中的方法/函数进行单元测试,但我仍然需要依赖模板中的 HTML 元素。一旦更改了 id(或在我的测试用例中用作选择器的属性),我的测试用例也需要更改!这不会违反单元测试的目的吗?
3 回答
javascript 单元测试中最困难的部分之一不是测试,而是学习如何构建代码以使其可测试。
您需要将可测试逻辑和 DOM 操作明确分离来构建代码。
我的经验法则是这样的:
如果您正在测试任何依赖于 DOM 结构的东西,那么您做错了。
总结:尝试仅测试数据操作和逻辑操作。
我恭敬地不同意@BentOnCoding。大多数情况下,组件不仅仅是它的类。组件结合了 HTML 模板和 JavaScript/TypeScript 类。这就是为什么您应该测试模板和类是否按预期协同工作的原因。仅类测试可以告诉您类行为。但是他们无法告诉您组件是否会正确呈现并响应用户输入。
有人说你应该在集成测试中测试它。但是集成测试的编写/运行速度较慢,运行/维护成本更高(在时间和资源方面)。因此,在集成测试中测试大部分组件功能可能会减慢您的速度。
这并不意味着您应该跳过集成测试。虽然集成和 E2E 测试可能比单元测试更慢且成本更高,但它们让您更加确信您的应用程序正在按预期工作。集成测试是将单个单元/组件组合在一起并作为一个组进行测试的地方。它不应被视为测试组件模板的唯一场所。
我想我第二次@BentOnCoding 的建议是你想要单元测试的是你的代码,而不是别的。当涉及到 DOM 操作时,就是浏览器代码,例如 appendChild、replaceChild 等。如果您使用 jQuery 或其他库,同样适用——您正在调用其他代码来执行操作,而您不需要不需要测试。那么你如何断言在你的视图模型/控制器上调用某些函数会产生你想要的 DOM 结构呢?你没有。就像您不会对在数据库上调用存储过程导致特定表中的特定行进行单元测试一样。相反,您需要考虑如何从操纵 DOM 的部分中抽象出控制器中处理输入/输出的部分。例如,如果您有一个基于某些条件调用 alert() 的方法,您可能希望将该方法分成两个:
- 接受和处理输入的一种
- 一个调用 window.alert()
在测试期间,您将 window.alert(或您的代理方法)替换为假的(请参阅 SinonJS),并使用引发(或不引发)警报的条件调用您的输入处理器。然后,您可以断言是否调用了 fake、多少次、使用什么值等不同的值。您实际上并不测试 window.alert(),因为它在您的代码之外。假设这些外部依赖项正常工作。如果他们不这样做,那么这就是该库的错误,但发现这些错误不是您的单元测试的工作。您只对验证自己的代码感兴趣。