Existe alguma maneira, usando o Mockito, de zombar de alguns métodos de uma classe, mas não de outros?
Por exemplo, nesta Stock
classe (admitidamente inventada) , quero zombar dos valores getPrice()
e getQuantity()
retornar (como mostrado no trecho de teste abaixo), mas quero getValue()
executar a multiplicação conforme codificado na Stock
classe
public class Stock {
private final double price;
private final int quantity;
Stock(double price, int quantity) {
this.price = price;
this.quantity = quantity;
}
public double getPrice() {
return price;
}
public int getQuantity() {
return quantity;
}
public double getValue() {
return getPrice() * getQuantity();
}
@Test
public void getValueTest() {
Stock stock = mock(Stock.class);
when(stock.getPrice()).thenReturn(100.00);
when(stock.getQuantity()).thenReturn(200);
double value = stock.getValue();
// Unfortunately the following assert fails, because the mock Stock getValue() method does not perform the Stock.getValue() calculation code.
assertEquals("Stock value not correct", 100.00*200, value, .00001);
}
Respostas:
Para responder diretamente à sua pergunta, sim, você pode zombar de alguns métodos sem zombar de outros. Isso é chamado de simulação parcial . Consulte a documentação do Mockito sobre zombarias parciais para obter mais informações.
Para o seu exemplo, você pode fazer algo como o seguinte, em seu teste:
Nesse caso, cada implementação de método é zombada, a menos que seja especificado
thenCallRealMethod()
nawhen(..)
cláusula.Existe também a possibilidade de o contrário com espião, em vez de simulação :
Nesse caso, toda a implementação do método é real, exceto se você definiu um comportamento simulado com
when(..)
.Há uma armadilha importante quando você usa o
when(Object)
espião, como no exemplo anterior. O método real será chamado (porquestock.getPrice()
é avaliado anteswhen(..)
no tempo de execução). Isso pode ser um problema se o seu método contiver lógica que não deve ser chamada. Você pode escrever o exemplo anterior assim:Outra possibilidade pode ser o uso
org.mockito.Mockito.CALLS_REAL_METHODS
, como:Isso delega chamadas não rotuladas para implementações reais.
No entanto, com o seu exemplo, acredito que ainda falhará, já que a implementação
getValue()
dependequantity
eprice
, em vez degetQuantity()
egetPrice()
, é o que você zombou.Outra possibilidade é evitar zombarias por completo:
fonte
Stock stock = spy(Stock.class);
Isso parece errado, ospy
método parece aceitar apenas objetos e não classes.doReturn(retval).when(spyObj).methodName(args)
ewhen(spyObj.methodName(args)).thenReturn(retval)
O mocking parcial de uma classe também é suportado via Spy no mockito
Verifique os documentos
1.10.19
e2.7.22
para obter explicações detalhadas.fonte
De acordo com os documentos :
fonte
class NaughtyLinkedList extends LinkedList { public int size() { throw new RuntimeException("don't call me");} } @Test public void partialMockNaughtLinkedList(){ List mock = mock(NaughtyLinkedList.class, CALLS_REAL_METHODS); mock.add(new Object()); // this calls the real function when(mock.size()).thenReturn(2); // For whatever reason, this lines throws the RuntimeException. assertEquals(2,mock.size()); }
Isso não funciona. Qualquer que seja o motivo, quando "quando" é executado, ele realmente executa o método que deveria ser ridicularizado. Código:O que você deseja é de
org.mockito.Mockito.CALLS_REAL_METHODS
acordo com os documentos:Assim, seu código deve se parecer com:
A chamada para
Stock stock = mock(Stock.class);
chamadasorg.mockito.Mockito.mock(Class<T>)
assim:Os documentos do valor
RETURNS_DEFAULTS
informam:fonte
withSettings()...
assim? Parece queorg.mockito.internal.stubbing.answers.CallsRealMethods()
(por exemplo) pode fazer o trabalho ... eo javadoc para esta classe especificamente diz que é para uso em simulações parciais ...thenReturn
, executará o método (o que pode causar problemas, embora não neste exemplo) e, portanto,doReturn
é preferível nesse caso ...?A zombaria parcial usando o método de espionagem do Mockito pode ser a solução para o seu problema, como já indicado nas respostas acima. Até certo ponto, concordo que, para o seu caso de uso concreto, talvez seja mais apropriado zombar da pesquisa do banco de dados. Pela minha experiência, isso nem sempre é possível - pelo menos não sem outras soluções alternativas - que consideraria muito complicadas ou pelo menos frágeis. Observe que essa zombaria parcial não funciona com versões aliadas do Mockito. Você usou pelo menos 1.8.0.
Eu teria acabado de escrever um comentário simples para a pergunta original, em vez de postar esta resposta, mas o StackOverflow não permite isso.
Só mais uma coisa: eu realmente não consigo entender que muitas vezes uma pergunta está sendo feita aqui, com o comentário "Por que você quer fazer isso" sem ao menos tentar entender o problema. Especialmente quando se trata de zombar parcialmente, há muitos casos de uso que eu poderia imaginar onde seria útil. É por isso que os caras da Mockito forneceram essa funcionalidade. Obviamente, esse recurso não deve ser usado em excesso. Mas quando falamos sobre configurações de casos de teste que de outra forma não poderiam ser estabelecidas de uma maneira muito complicada, a espionagem deve ser usada.
fonte