Quando a propriedade é definida no banco de dados de produção (ou um clone para teste), isso não é um teste de unidade . Um teste de unidade verifica uma unidade de trabalho e não requer um estado externo específico para funcionar. Isso pressupõe que Offer1
seja definido no banco de dados para ser uma oferta somente para homens. Isso é estado externo. Então, isso é mais um teste de integração , especificamente um system ou acceptance . Observe que os testes de aceitação geralmente não são roteirizados (não executados em uma estrutura de teste, mas executados manualmente por seres humanos).
Quando a propriedade é definida no modelo de domínio com uma instrução if
, o mesmo teste é um teste de unidade. E isso pode ser frágil. Mas o verdadeiro problema é que o código é frágil. Como regra geral, seu código será mais resiliente se o comportamento de negócios for configurável em vez de codificado. Porque uma implantação urgente para corrigir um pequeno erro de codificação deve ser rara. Mas um requisito comercial que muda sem aviso prévio é apenas uma terça-feira (algo que acontece semanalmente).
Você pode estar usando uma estrutura de teste de unidade para executar o teste. Mas as estruturas de teste de unidade não se limitam a executar testes de unidade. Eles podem e executam testes de integração também.
Se você estivesse escrevendo um teste de unidade, criaria person
e offer1
do zero sem depender do estado do banco de dados. Algo como
[Fact]
public void ReturnsFalseWhenGivenAPersonWithAGenderOfFemale()
{
var personId = Guid.NewGuid();
var gender = "F";
var person = new Person(personId, gender);
var id = Guid.NewGuid();
var offer1 = new Offer1(id, "ReturnsFalseWhenGivenAPersonWithAGenderOfFemale");
offer1.markLimitedToGender("M");
Assert.False(offer1.IsEligible(person));
}
Observe que isso não muda com base na lógica de negócios. Não está afirmando que offer1
rejeita as mulheres. Está fazendo offer1
o tipo de oferta que rejeita as mulheres.
Você pode criar e configurar o banco de dados como parte do teste. Em C #, usando o NUnit, ou no Java JUnit, você configuraria o banco de dados em um método Setup
. Presumivelmente, sua estrutura de teste tem uma noção semelhante. Nesse método, você poderia inserir registros no banco de dados com o SQL.
Se for difícil para você escrever um código que substitua um banco de dados de teste para o banco de dados de produção, isso parece uma fraqueza de teste em seu aplicativo. Para testes, seria melhor usar algo como injeção de dependência que permita a substituição. Então você poderia escrever testes que são independentes das regras de negócios atuais.
Um benefício colateral disso é que muitas vezes é mais fácil para o proprietário da empresa (não necessariamente o proprietário da empresa, mais como a pessoa responsável por esse produto na hierarquia corporativa) configurar as regras de negócios diretamente. Porque, se você tiver esse tipo de estrutura técnica, será fácil permitir que o proprietário da empresa use uma interface do usuário (UI) para configurar a oferta. O proprietário da empresa selecionaria a limitação na interface do usuário e emitiria a chamada markLimitedToGender("M")
. Então, quando a oferta for mantida no banco de dados, ela será armazenada. Mas você não precisaria armazenar a oferta para usá-lo. Portanto, seus testes podem criar e configurar uma oferta que não existe no banco de dados.
Em seu sistema, conforme descrito, o proprietário da empresa teria que fazer uma solicitação ao grupo técnico, que emitiria o SQL apropriado e atualizaria os testes. Ou o grupo técnico tem que editar seu código e testes (ou testes então codificam). Isso parece uma abordagem bastante pesada. Você consegue. Mas o seu software (não apenas o seu teste) seria menos frágil se você não tivesse que fazê-lo.
TL; DR : você pode escrever testes como esse, mas talvez seja melhor escrever seu software para não precisar fazê-lo.