Я полностью за решение Эрана Харела, и в случаях, когда это невозможно, предложение Томаша Нуркевича о шпионаже превосходно.Однако стоит отметить, что бывают ситуации, когда ни один из них не применим.Например, если метод 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
}
}