如何在Mockito中模拟经JaxWsProxyFactoryBean转换的GenericService对象?
问题根源
你遇到的问题和类型转换无关——isValidCode方法内部直接实例化JaxWsProxyFactoryBean并创建GenericService真实代理对象,导致你mock的GenericService实例根本没有被用到,测试时自然会调用实际的Web服务方法。
解决方案
推荐通过重构代码解耦服务创建逻辑,让测试时能够替换为mock对象,以下是几种可行方案:
方案1:抽离服务创建逻辑为可重写方法
在原类中将GenericService的创建逻辑抽成protected方法,测试时通过子类重写该方法返回mock对象:
重构原类
public class YourClass { private String genericServiceName; // 抽离服务创建逻辑,方便测试重写 protected GenericService createGenericService() { JaxWsProxyFactoryBean proxy = new JaxWsProxyFactoryBean(); proxy.setServiceClass(GenericService.class); proxy.setServiceName(new QName(this.genericServiceName)); // 其他代理配置 return (GenericService) proxy.create(); } public boolean isValidCode(String code) { GenericService service = createGenericService(); // 假设GenericExists包含isExists()方法返回boolean结果 return service.exists(new CodeInput(code)).isExists(); } // 提供setter方法设置genericServiceName public void setGenericServiceName(String genericServiceName) { this.genericServiceName = genericServiceName; } }
编写TestNG测试用例
import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import static org.mockito.Mockito.*; public class YourClassTest { @Mock private GenericService serviceMock; @Mock private GenericExists mockExistsResponse; private YourClass testInstance; @BeforeMethod public void setUp() { MockitoAnnotations.openMocks(this); // 创建子类重写服务创建方法,返回mock对象 testInstance = new YourClass() { @Override protected GenericService createGenericService() { return serviceMock; } }; testInstance.setGenericServiceName("http://example.com/GenericService"); } @Test public void testIsValidCode_ReturnsTrue() { // 模拟exists方法的返回结果 when(mockExistsResponse.isExists()).thenReturn(true); when(serviceMock.exists(any(CodeInput.class))).thenReturn(mockExistsResponse); boolean result = testInstance.isValidCode("TEST_CODE"); assert result == true; // 验证mock方法被调用 verify(serviceMock).exists(any(CodeInput.class)); } }
方案2:依赖注入(推荐,适合有DI框架的项目)
如果项目使用Spring等依赖注入框架,直接将GenericService作为依赖注入到类中,测试时注入mock对象即可:
重构原类
public class YourClass { private final GenericService genericService; // 构造注入GenericService public YourClass(GenericService genericService) { this.genericService = genericService; } public boolean isValidCode(String code) { return genericService.exists(new CodeInput(code)).isExists(); } }
编写TestNG测试用例
import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import static org.mockito.Mockito.*; public class YourClassTest { @Mock private GenericService serviceMock; @Mock private GenericExists mockExistsResponse; private YourClass testInstance; @BeforeMethod public void setUp() { MockitoAnnotations.openMocks(this); testInstance = new YourClass(serviceMock); } @Test public void testIsValidCode_ReturnsTrue() { when(mockExistsResponse.isExists()).thenReturn(true); when(serviceMock.exists(any(CodeInput.class))).thenReturn(mockExistsResponse); boolean result = testInstance.isValidCode("TEST_CODE"); assert result == true; verify(serviceMock).exists(any(CodeInput.class)); } }
方案3:PowerMock mock构造方法(不推荐,仅用于无法重构代码的场景)
如果无法修改原类,可以用PowerMock mockJaxWsProxyFactoryBean的构造和create方法,强制返回mock对象:
编写TestNG测试用例
import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.testng.PowerMockTestCase; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import static org.mockito.Mockito.*; @PrepareForTest({YourClass.class, JaxWsProxyFactoryBean.class}) public class YourClassTest extends PowerMockTestCase { @Mock private GenericService serviceMock; @Mock private JaxWsProxyFactoryBean proxyMock; @Mock private GenericExists mockExistsResponse; private YourClass testInstance; @BeforeMethod public void setUp() throws Exception { MockitoAnnotations.openMocks(this); testInstance = new YourClass(); testInstance.setGenericServiceName("http://example.com/GenericService"); // mock JaxWsProxyFactoryBean的构造函数 PowerMockito.whenNew(JaxWsProxyFactoryBean.class).withNoArguments().thenReturn(proxyMock); // mock create方法返回mock的GenericService when(proxyMock.create()).thenReturn(serviceMock); } @Test public void testIsValidCode_ReturnsTrue() { when(mockExistsResponse.isExists()).thenReturn(true); when(serviceMock.exists(any(CodeInput.class))).thenReturn(mockExistsResponse); boolean result = testInstance.isValidCode("TEST_CODE"); assert result == true; verify(proxyMock).setServiceClass(GenericService.class); verify(serviceMock).exists(any(CodeInput.class)); } }
内容的提问来源于stack exchange,提问作者TechGoose
相关产品推荐
相关产品推荐

