Java中如何Mock第三方服务器响应 解决单元测试连接真实服务问题
问题根因
你当前的测试逻辑存在两个核心错误:
- 对需要测试的目标类
ModuleSpectator直接执行了Mock:Mock对象的方法默认不会执行真实业务逻辑,你需要测试getTotalModules的真实实现,因此不应该Mock这个类。 - 业务方法内部直接通过
new Server(server_ip)生成Server实例:你在测试代码中Mock的serverMock和业务逻辑里生成的真实Server对象没有任何关联,因此程序还是会初始化真实的Server实例,触发第三方服务连接。
解决方案
方案1:调整业务代码使用依赖注入(推荐)
这是符合可测试性设计的最优方案,只需调整业务代码将Server依赖从方法内部创建改为外部注入:
class ModuleSpectator { // 将Server作为成员变量,通过构造方法注入 private Server server; public ModuleSpectator(Server server) { this.server = server; } public long getTotalModules(String server_id){ ServerState serverState = server.getServerState(server_id); return (long) serverState.getTotalModules(); } }
对应的测试代码调整如下:
@Test public void testGetTotalModules(){ String server_id = "ser_01"; // Mock Server依赖 Server serverMock = mock(Server.class); ServerState serverState = new ServerState(); serverState.setTotalModules(50); when(serverMock.getServerState(server_id)).thenReturn(serverState); // 初始化真实的待测类实例,传入Mock好的Server对象 ModuleSpectator moduleSpectator = new ModuleSpectator(serverMock); // 执行断言 assertEquals(50, moduleSpectator.getTotalModules(server_id)); }
方案2:不修改原业务代码,Mock构造方法
如果你无法改动原有业务代码,可以使用Mockito 3.4及以上版本提供的mockConstruction能力,Mock Server类的所有构造方法,让业务逻辑中new出来的Server都是你预设的Mock对象:
@Test public void testGetTotalModules(){ String server_id = "ser_01"; ServerState serverState = new ServerState(); serverState.setTotalModules(50); // 拦截所有Server类的构造调用,统一返回预设好桩的Mock对象 try (MockedConstruction<Server> mockedServer = mockConstruction(Server.class, (mock, context) -> { when(mock.getServerState(server_id)).thenReturn(serverState); })) { // 初始化真实的待测类实例 ModuleSpectator moduleSpectator = new ModuleSpectator(); // 执行断言 assertEquals(50, moduleSpectator.getTotalModules(server_id)); } }
内容的提问来源于stack exchange,提问作者thatGuy
相关产品推荐
相关产品推荐

