对于 Java 测试,我应该模拟客户端还是模拟服务器
Posted
技术标签:
【中文标题】对于 Java 测试,我应该模拟客户端还是模拟服务器【英文标题】:For Java testing, should I mock client or mock the server 【发布时间】:2019-03-11 17:26:06 【问题描述】:在客户端-服务器架构中,什么时候应该模拟客户端,什么时候应该模拟服务器,最好的方法应该是什么。我知道单元测试应该只测试给定的类,每个依赖对象都被模拟,而集成测试应该测试一个整体的特性。当涉及到 API 调用时,我很困惑应该模拟用于 api 调用的客户端,还是应该使用一些服务器模拟框架并让真实的客户端调用模拟服务器。
我有一种情况,我应该(不是强制性的)测试我是否点击了正确的 API url、使用正确的方法以及在查询参数或请求正文中传递了某些值。通过客户端模拟,我可以简单地“验证”给定参数(路径、方法、请求正文)是否通过并认为测试成功。如果我要模拟服务器,那么我需要在模拟服务器上创建一点处理来检查路径、方法和请求主体是否正确传递并返回一个值。在这种情况下,服务器响应是我唯一可以用来衡量测试是否成功(如果未收到所需数据,则发送 500)。
根据您的经验,在客户端-服务器架构中测试调用以进行集成测试的正确方法是什么?如果我们按照书本行事,那么应该使用服务器模拟,但在上述情况下这是否实用?对于单元测试,很明显应该使用模拟。
更新:为避免混淆:我正在创建一个依赖于我无法控制的公开可用服务的客户端。因此,我正在测试客户端是否正常工作并且重点是客户端。问题是我应该(在集成测试中)模拟负责远程连接的客户端对象(在我的情况下来自 Play 框架的 WSClient),还是应该使用一些服务器模拟(如 okhttp 模拟 Web 服务器)。
另一个更新: 大多数人建议应该遵循简单的经验法则:如果这些是单元测试,则模拟客户端,如果这些是集成测试,则使用模拟服务器。现在,我对这种情况感到好奇:我有一个依赖于 B 类的 A 类,而 B 类有一个负责远程调用的客户端对象。如果我要为 A 类编写单元测试,我应该模拟 B 类,这很好。但是,如果我正在对 A 类进行集成测试,是否可以在 B 类中模拟客户端对象并“验证”是否将适当的参数传递给它(路径、方法和请求正文),或者为了完整起见,即使模拟客户端对象更容易,我也应该运行模拟服务器。在这种情况下,我不会测试超时和低级网络错误。或者,在这种情况下,集成测试的重点也应该是测试网络连接性。
【问题讨论】:
当前测试是为哪个组件编写的?在这种情况下,“服务器”是一个非常灵活的概念。您的服务器组件可能正在使用其他 HTTP 服务,从而成为模拟服务器的客户端。如果测试的重点是客户端,那么您可以模拟服务器。在这里,您的问题变得有点不清楚。但是,如果担心的是要测试您应该测试的系统组件,那么也许您应该研究使用代理(mock-server、hoverfly 等)存根外部请求的服务虚拟化工具。 我倾向于使用 junit 来驱动作为最小可测试单元的非平凡测试(即使这意味着在进程中运行客户端和服务器) 我应该在问题中更好地定义这一点:我正在创建一个依赖于我无法控制的公开可用服务的客户。因此,我正在测试客户端是否正常工作并且重点是客户端。 【参考方案1】:你需要:
-
集成测试 - 使用 Wiremock 之类的存根服务器,测试超时、格式错误的响应、500 等真实场景。
测试您的客户端类 - 使用 Mockito 模拟服务器端点并验证响应
【讨论】:
好的,所以您建议集成测试的目的应该是测试网络连接和服务器可以发送回的各种响应。对于#2,我不太明白测试客户端类是什么意思:您是指单元测试(在这种情况下,服务器模拟没有多大意义),还是您指的是另一种类型的测试我应该只测试以验证我发送的内容? 您最初询问如何检查您的客户端是否使用参数访问了正确的 api 端点。答案是:只需用 Mockito 模拟这个端点,我不会告诉你怎么做,因为我不知道你在使用什么框架。那将是您的客户端类的单元测试。使用存根服务器,您可以进行真正的端到端测试。这是必要的,我认为这就是集成测试。我帮你了吗? 感谢您的回答。一般来说,我的问题与首选哪种方法有关:模拟客户端调用或模拟服务器。如何做到这一点不是问题的一部分。大多数人建议应该遵循简单的经验法则:如果这些是单元测试,则模拟客户端,如果这些是集成测试,则使用模拟服务器。我会更准确地更新问题。以上是关于对于 Java 测试,我应该模拟客户端还是模拟服务器的主要内容,如果未能解决你的问题,请参考以下文章