Eu tenho uma aula como abaixo:
public class A {
public A(String test) {
bla bla bla
}
public String check() {
bla bla bla
}
}
A lógica no construtor A(String test)
e check()
são as coisas que estou tentando zombar. Eu quero qualquer chamada como: new A($$$any string$$$).check()
retorna uma string fictícia "test"
.
Eu tentei:
A a = mock(A.class);
when(a.check()).thenReturn("test");
String test = a.check(); // to this point, everything works. test shows as "tests"
whenNew(A.class).withArguments(Matchers.anyString()).thenReturn(rk);
// also tried:
//whenNew(A.class).withParameterTypes(String.class).withArguments(Matchers.anyString()).thenReturn(rk);
new A("random string").check(); // this doesn't work
Mas não parece estar funcionando. new A($$$any string$$$).check()
ainda está passando pela lógica do construtor em vez de buscar o objeto simulado de A
.
Respostas:
O código que você postou funciona para mim com a versão mais recente do Mockito e do Powermockito. Talvez você não tenha preparado A? Experimente isto:
A.java
public class A { private final String test; public A(String test) { this.test = test; } public String check() { return "checked " + this.test; } }
MockA.java
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(A.class) public class MockA { @Test public void test_not_mocked() throws Throwable { assertThat(new A("random string").check(), equalTo("checked random string")); } @Test public void test_mocked() throws Throwable { A a = mock(A.class); when(a.check()).thenReturn("test"); PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a); assertThat(new A("random string").check(), equalTo("test")); } }
Ambos os testes devem passar com mockito 1.9.0, powermockito 1.4.12 e junit 4.8.2
fonte
PrepareForTest
Pelo que sei, você não pode simular construtores com mockito, apenas métodos. Mas de acordo com o wiki na página de código Mockito do google, há uma maneira de simular o comportamento do construtor criando um método em sua classe que retorna uma nova instância dessa classe. então você pode zombar desse método. Abaixo está um trecho diretamente do wiki Mockito :
Se você está apenas querendo retornar um objeto simulado de sua classe, acho que isso deve funcionar para você. Em qualquer caso, você pode ler mais sobre criação de objeto de simulação aqui:
http://code.google.com/p/mockito/wiki/MockingObjectCreation
fonte
Sem usar Powermock .... Veja o exemplo abaixo com base na resposta de Ben Glasser, já que demorei um pouco para descobrir .. espero que economize algum tempo ...
Aula Original:
public class AClazz { public void updateObject(CClazz cClazzObj) { log.debug("Bundler set."); cClazzObj.setBundler(new BClazz(cClazzObj, 10)); } }
Classe modificada:
@Slf4j public class AClazz { public void updateObject(CClazz cClazzObj) { log.debug("Bundler set."); cClazzObj.setBundler(getBObject(cClazzObj, 10)); } protected BClazz getBObject(CClazz cClazzObj, int i) { return new BClazz(cClazzObj, 10); } }
Classe de Teste
public class AClazzTest { @InjectMocks @Spy private AClazz aClazzObj; @Mock private CClazz cClazzObj; @Mock private BClazz bClassObj; @Before public void setUp() throws Exception { Mockito.doReturn(bClassObj) .when(aClazzObj) .getBObject(Mockito.eq(cClazzObj), Mockito.anyInt()); } @Test public void testConfigStrategy() { aClazzObj.updateObject(cClazzObj); Mockito.verify(cClazzObj, Mockito.times(1)).setBundler(bClassObj); } }
fonte
Com mockito você pode usar withSettings (), por exemplo, se o CounterService requer 2 dependências, você pode passá-las como uma simulação:
UserService userService = Mockito.mock(UserService.class); SearchService searchService = Mockito.mock(SearchService.class); CounterService counterService = Mockito.mock(CounterService.class, withSettings().useConstructor(userService, searchService));
fonte
Mockito tem limitações para testar métodos finais, estáticos e privados.
com a biblioteca de testes jMockit, você pode fazer poucas coisas muito fáceis e diretas como a seguir:
Construtor de simulação de uma classe java.io.File:
new MockUp<File>(){ @Mock public void $init(String pathname){ System.out.println(pathname); // or do whatever you want } };
Zombe de um método estático:
fonte