Para corrigir um erro em um aplicativo, modifiquei um método chamado postLogin
adicionando uma chamada a um método existente chamado getShoppingCart
.
Código
protected void postLogin() {
getShoppingCart();
}
No entanto, não sei ao certo qual é a melhor maneira de escrever um teste de unidade postLogin
.
Abordagem 1
Use o check do Mockito para simplesmente verificar se o método foi chamado.
verify(mock).getShoppingCart();
Abordagem 2
Teste o efeito colateral da chamada do método, buscando o valor do carrinho de compras do usuário.
AssertNotNull(user.getShoppingCart());
Uma abordagem é melhor que a outra?
getShoppingCart()
método tenha efeitos colaterais, você não precisa testar como ele é chamado. Se tiver efeitos colaterais, você realmente deve mudar seu nome, porque osgetXXX()
métodos convencionalmente devem ser idempotentes.getNextValue
? Indiscutivelmente, alguém poderia dizer "Não chame isso de getter; mude o nome paranextValue
", mas eu já vigetNext
usado antes. Talvez um exemplo melhor seja um objeto representando um elétron; o que acontece quando ligogetPosition
? Ou pior,getPosition(); getVelocity();
Respostas:
Eu normalmente preferiria o método 2.
Por quê? Como você deseja
postLogin
alterar algum estado do seu sistema, mas como ele realiza isso (e quais métodos chama internamente para isso) é apenas um detalhe da implementação, nada sobre o qual o seu teste de unidade deve fazer suposições. Então é melhor fazer seu teste apenas verificando o estado final.fonte
Eu mudaria o getShoppingCart para algo como initializeShoppingCart, o objetivo do método deve ser claro para quem o lê, sem a necessidade de verificar o que o método faz e os efeitos colaterais como esse podem causar um comportamento surpreendente para os usuários do método.
Se getShoppingCart estiver em outra classe e já tiver sido testado em unidade, eu usaria a abordagem 1 - não há necessidade de testar novamente o que já foi testado. Nesse caso, temos certeza de que o getShoppingCart funciona corretamente e queremos apenas garantir que seja chamado a partir do postLogin. Se alguém no futuro remover essa chamada, o teste falhará.
Se getShoppingCart for um método privado que não possa ser testado por si só, eu usaria a abordagem 2, para garantir que, quando postLogin for chamado, a funcionalidade desejada de getShoppingCart seja executada conforme o esperado.
fonte
Ao testar uma chamada de função (nula ou não) com efeito colateral, é mais completo testar se o efeito colateral não ocorre apenas, mas verificar se o efeito colateral (saída do sistema ou alteração de estado) é o desejado.
fonte
Não discutirei seu design, mas, no seu caso, eu adotaria a primeira abordagem, porque o teste de unidade é para testar quais métodos fazem tecnicamente, independentemente do trabalho deles no domínio, ou seja, o que o seu método
postLogin
faz? Tecnicamente, ele chama,getShoppingCard
então você precisa testar o que realmente está chamandogetShoppingCard
, eu também criaria outro teste paragetShoppingCard
testar o que ele faz e, se tiver efeitos colaterais, eu o verificarei dentro desse novo teste.fonte
Você tem um erro no postLogin. Portanto, a primeira coisa que você deve fazer é criar um teste de unidade que, ao chamar o postLogin sem o conjunto esperado de informações, "falhará".
A partir da idéia acima, outra alternativa das 2 propostas é injetar as informações sobre o carrinho de compras como parâmetro. Se você não tiver as informações corretas, lança uma exceção desmarcada. Isso deixará claro que, sem os detalhes corretos, seu método está condenado.
Isso exigirá uma pequena alteração, onde o cliente que está chamando o postLogin agora é necessário para também passar as informações do carrinho de compras. Para mim, isso ainda é coerente agora que você vê que eles estão acoplados. Esse acoplamento será realizado pelo chamador.
Então você nem precisaria testar o getShoppingCart dentro do postLogin porque o método real em teste é o postLogin. É aquele que possui o bug e o único que requer correção e validação adequadas. Com a dependência injetada, você poderá testá-lo facilmente sob diferentes condições e confirmar que nenhum erro foi gerado.
fonte