Agora vamos falar sobre afirmações.
As afirmações são uma das coisas tomadas como certas, então tudo aqui parece ser especialista. Alguém usa Java ou Junit embutido, alguém usa bibliotecas avançadas, alguém constrói a sua.
Mas vamos tentar abordar isso mais a sério. Como, de fato, certo?
Primeiro, asserções duplicam a especificação. Se a especificação shouldReturnValidOrder for especificada, isso deve ser verificado e não assertNotNull.
Em segundo lugar, as afirmações devem ser fáceis de ler. Ou seja, instantaneamente, comparando com a especificação.
Se houver muitas afirmações (para meu gosto extremo, há muito mais que uma, mas colocamos um limite de pelo menos cinco a sete), o teste deixa de ser compreensível. Para sempre, cada teste deve ter apenas um motivo para cair.
Os ativos podem ser direcionados para: um campo primitivo, objeto, coleção, raramente uma função ou thunk.
Quanto mais complexo o objeto, mais complexas e diversas serão as afirmações e mais difícil será ler e encontrar erros.
As afirmações positivas são melhores que as negativas duplas.
Os métodos padrão são lidos melhor do que os auxiliares personalizados. (Quem sabe quem e onde testou a biblioteca de ajudantes). E as afirmações devem estar no corpo do método de teste, e não em algum lugar na parte de trás dos auxiliares de teste (o sonar jura com razão pela falta de afirmações).
Ativos sobre campos são mais compreensíveis que afirmações sobre objetos e, especialmente, sobre coleções.
No caso de campos aninhados, faz sentido testar completamente.
Não
assertNotNull(order.getCustomer().getName)
mas
assertNotNull(order) assertNotNull(order.getCustomer()) assertNotNull(order.getCustomer().getName())
Os assers não apenas checam estupidamente o que é retornado do método, mas o influenciam. E se podemos mudar, precisamos mudar.
É relativamente difícil fazer afirmações sobre coleções. Eles contêm zeros, são classificados, exatamente como são classificados, como os elementos são verificados quanto à igualdade etc. - tudo isso torna as coleções objetos difíceis para afirmações, especialmente quando existe lógica no método relacionado aos elementos das coleções.
Portanto, um método como:
List<Order> getOrderList(List<OrderDao> orderDaoList){ return orderDaoList.stream().map(orderDao=>order.name(orderDao.getName).build()).collect(Collectors.toList()) }
é fácil dividir em dois, um transformador orderDao => order e testá-lo separadamente, e o segundo testará o mapeamento de coleções no mapeador abstrato, e podemos testá-lo no stub.
List<Order> getOrderList(List<OrderDao> orderDaoList, OrderDaoToOrderMapper mapper){ return orderDaoList.stream().map(mapper::map).collect(Collectors.toList()) }
Por outro lado, as coleções se prestam bem à tipificação e expansão, ou seja, podemos fazer com relativa facilidade uma coleção de seu próprio tipo com todas as propriedades testadas, co- e contravariância etc. Portanto, em vez de uma lista genérica, poderíamos criar nossa própria OrderList, ou OrderSet ou OrderSortedSet e, quanto mais específico, melhor. E os testes se tornarão mais fáceis.
Fazer declarações sobre funções não é muito mais complicado do que sobre objetos, e elas são bem digitadas em alguns idiomas; portanto, você provavelmente pode recomendar uma digitação melhor, ou seja, em vez de Func <Order, Order>, retorne algum OrderComparator.