我完全支持Eran Harel的解决方案,在不可能使用它的情况下,Tomasz Nurkiewicz的间谍建议非常出色。然而,值得注意的是,有些情况下两种方法都不适用。例如,如果login
方法有点“庞大”:
public class TestedClass {
public LoginContext login(String user, String password) {
LoginContext lc = new LoginContext("login", callbackHandler);
lc.doThis();
lc.doThat();
return lc;
}
}
......而且这是旧代码,无法重构以将新的LoginContext
的初始化提取到自己的方法中并应用前面提到的解决方案之一。
为了完整起见,值得一提的是第三种技术-使用PowerMock在调用new
运算符时注入模拟对象。然而,PowerMock不是万能的。它通过对所模拟的类进行字节码操作来工作,如果被测试的类采用字节码操作或反射可能会出现问题,至少从我的个人经验来看,已知会对测试产生性能影响。不过,如果没有其他选择,唯一的选项必须是好的选项:
@RunWith(PowerMockRunner.class)
@PrepareForTest(TestedClass.class)
public class TestedClassTest {
@Test
public void testLogin() {
LoginContext lcMock = mock(LoginContext.class);
whenNew(LoginContext.class).withArguments(anyString(), anyString()).thenReturn(lcMock);
TestedClass tc = new TestedClass();
tc.login ("something", "something else");
}
}
编辑:
现代版本的Mockito提供了类似的功能,无需额外使用PowerMock库,只需添加mockito-inline
依赖(而不是mockito-core
依赖)即可:
public class TestedClassTest {
@Test
public void testLogin() {
try (MockedConstruction<LoginContext> mockedConstruction =
Mockito.mockConstruction(LoginContext.class)) {
TestedClass tc = new TestedClass();
tc.login("something", "something else");
}
}
}
new()
是否确实返回一个新实例。 :) - shazwashere