3 回答
TA贡献1828条经验 获得超6个赞
对于将来,我会推荐伊兰·哈雷尔(Eran Harel)的答案(将new工厂搬迁到可以嘲笑的工厂)。但是,如果您不想更改原始源代码,请使用非常方便且独特的功能:spies。从文档中:
您可以创建真实对象的间谍。当您使用间谍时,将调用实际方法(除非对方法进行了加注)。
真正的间谍应该小心谨慎地使用,例如在处理遗留代码时。
在您的情况下,您应该写:
TestedClass tc = spy(new TestedClass());
LoginContext lcMock = mock(LoginContext.class);
when(tc.login(anyString(), anyString())).thenReturn(lcMock);
TA贡献1775条经验 获得超8个赞
我全力支持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();
}
}
...这是旧代码,无法重构以提取新的初始化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");
// test the login's logic
}
}
TA贡献1799条经验 获得超8个赞
您可以使用工厂来创建登录上下文。然后,您可以模拟工厂并返回您想要进行测试的任何内容。
public class TestedClass {
private final LoginContextFactory loginContextFactory;
public TestedClass(final LoginContextFactory loginContextFactory) {
this.loginContextFactory = loginContextFactory;
}
public LoginContext login(String user, String password) {
LoginContext lc = loginContextFactory.createLoginContext();
}
}
public interface LoginContextFactory {
public LoginContext createLoginContext();
}
添加回答
举报