Simulação de sincronização com implementações reais

O problema de sincronização aparece sempre que as estratégias de teste são discutidas. Basicamente - por causa da carga adicional que os mokas criam para os desenvolvedores e também pelos riscos dos produtos divergir das dependências reais.

Então, de que maneira é mais barato garantir a sincronização de mokas com implementações reais?

Para sincronização, podemos escrever um teste que executa as mesmas verificações no mok e na implementação real.

Parece algo assim (eu escrevo sem DI, mas com DI é mais simples e mais correto):

public abstract class AbstractValidOrderDaoTest(){ Dao dao; public abstract arrange(); @Test public void whenValidOrderInDb_thenReturnValidOrder(){ arrange(); Order order = dao.retrieve(); assertNotNull(order); assertNotNull(order.getCustomerName()); //    } } public class ValidOrderDaoTest extends AbstractOrderDaoTest(){ @Override public void arrange(){ dao = new FakeValidOrderDao(); } } public class OrderDaoTest extends AbstractOrderDaoTest(){ @Override public void arrange(){ dao = new RealOrderDao(new ValidOrderDataSource(url, user, pwd)); } } 

OrderDaoTest funciona contra um objeto real com uma simulação ou dependência real subjacente, e ValidOrderDaoTest funciona contra uma simulação.

Se ValidOrderDataSource for um banco de dados real, o OrderDaoTest estará em um pacote separado e será executado como parte dos testes de integração, que podem falhar de tempos em tempos ao atualizar o banco de dados, por exemplo. Isso não deve interferir no CI \ CD.

Se ValidOrderDataSource for um banco de dados falso, o OrderDaoTest será executado juntamente com o restante dos testes de unidade.

Como a sincronização simulada envolve testar uma classe real, então para
a classe real terá que mexer com suas dependências subjacentes. Além disso, o vício em Mok subjacente deve se comportar de acordo com o cenário do Mok sobrejacente. No nosso caso, isso
ValidOrderDataSource.

Se você pensa sobre isso, faz sentido - qualquer afirmação sobre o comportamento de classes superiores implica implicitamente algum cenário nos subjacentes. Se o controlador retornar algo do serviço, seria bom se a base pudesse fornecê-lo.

Por outro lado, as classes mais altas geralmente vivem com idéias irrealistas sobre as classes mais baixas, por isso não é ruim remover scripts desnecessários.

A recursão sugere que, para tornar a simulação de nível superior sincronizada, é necessário iniciar a sincronização de todas as simulações subjacentes até dependências externas.

Isso torna a especificação do sistema ainda mais transparente, pois os cenários mais gerais e abstratos dependem de outros mais particulares.

Observe também que existem mokas que não precisam ser sincronizados. I.e. não temos uma implementação tão real que precisaria ser testada em conjunto. Isso se aplica aos principais cenários de erro. EmptyResultException_Datasource por exemplo Isso reduz bastante o número de testes cruzados necessários.

A sincronização é certamente necessária por dependências externas reais, como filas, serviços externos, bancos de dados - especialmente no que diz respeito aos dados que eles recebem e retornam.

Se o serviço externo mudar repentinamente, o que geralmente ocorre no estágio de desenvolvimento, não temos como verificar seu comportamento se não escrevermos um teste de sincronização.

Em termos de intensidade do trabalho. Em si, já temos um teste de classe real com algumas dependências simuladas arbitrárias. Comparado a testes não sincronizados, precisamos fazer algumas coisas.

  • destacar agir e afirmar em um teste abstrato
  • faça um teste específico para moka
  • corrigir dependências simuladas em um teste de classe real
  • se desejado, conclua repetidamente recursivamente até dependências externas.

Source: https://habr.com/ru/post/pt474964/


All Articles