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();
}
添加回答
舉報