Je suis tout à fait pour La solution d'Eran Harel et dans les cas où cela n'est pas possible, La suggestion de Tomasz Nurkiewicz pour l'espionnage est excellent. Toutefois, il convient de noter qu'il existe des situations où ni l'un ni l'autre ne s'applique. Par exemple, si le login
était un peu plus "musclée" :
public class TestedClass {
public LoginContext login(String user, String password) {
LoginContext lc = new LoginContext("login", callbackHandler);
lc.doThis();
lc.doThat();
return lc;
}
}
... et il s'agissait d'un vieux code qui ne pouvait pas être remanié pour extraire l'initialisation d'une nouvelle LoginContext
à sa propre méthode et appliquer l'une des solutions susmentionnées.
Par souci d'exhaustivité, il convient de mentionner une troisième technique - l'utilisation de PowerMock pour injecter l'objet fantaisie lorsque le new
est appelé. PowerMock n'est pas une solution miracle, cependant. Il fonctionne en appliquant la manipulation du byte-code sur les classes qu'il asservit, ce qui pourrait être une pratique douteuse si les classes testées utilisent la manipulation du byte-code ou la réflexion et, du moins d'après mon expérience personnelle, est connu pour introduire un impact sur les performances du test. Mais encore une fois, s'il n'y a pas d'autres options, la seule option doit être la bonne :
@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
}
}