Como simular eventos que causam exceções para testar blocos de tentativa / captura?

14

Entendo como as exceções funcionam e como capturá-las e manipulá-las em C #, mas como posso simular eventos que podem causar uma exceção para garantir que ela seja capturada corretamente? Por exemplo, é possível executar um aplicativo em um tipo de ambiente de teste em que é possível simular problemas de rede, problemas de banco de dados, etc.? As exceções por natureza parecem difíceis de reproduzir, dificultando a garantia de que seu código possa lidar com elas.

Embora eu desenvolva principalmente usando C # / .NET / Visual Studio, respostas ou recursos relacionados a outros idiomas podem ser úteis.

Piers Myers
fonte
Outra solução possível é descrita neste artigo do MSDN: Teste de injeção de falhas com TestApi
Giorgi

Respostas:

13

1) Se você seguisse o modelo de injeção de dependência, poderia substituir implementações reais de certas partes pelas zombarias, que lançariam exceções conforme necessário. No entanto, isso exigiria que você inicialmente projetasse seu aplicativo de uma maneira específica ou o reorganizasse completamente.

Gostar:

public class SqlUsersRepository : IUsersRepository
{
    public void RegisterNewUser (User newUser)
    {
        throw new SqlException ("Connection timeout");
    }
}

Aqui, no entanto, teríamos o problema de que o código do consumidor não deveria se preocupar em lidar com exceções concretas de implementação.

2) Outra abordagem é substituir determinadas chamadas de método pelos invólucros personalizados.

Ao invés de:

FileStream fs = File.OpenRead (path);

você usa:

FileStream fs = File.OpenRead_Test (path);

fornecendo um método de extensão personalizado (apenas uma ideia rápida):

public static FileStream OpenRead_Test (this System.IO.File file, string path)
{
    throw new FileNotFoundException ();
}

fonte
3

Você precisa examinar estruturas de simulação.

Com eles, você usa a injeção de dependência para chamar o banco de dados falso (por exemplo), em vez do banco de dados real. Isso significa que você tem controle total sobre o que é retornado para cada chamada.

Em seguida, você configura um teste que, quando chamado, lança a exceção desejada:

public void Test1()
{
    throw new NullArgumentException();
}

Seu teste passa quando seu código lida com isso corretamente.

ChrisF
fonte
3

A zombaria e a injeção só podem levar você até aqui e, em alguns casos, exigem grandes mudanças de abordagem.

Se você não deseja reprojetar seu aplicativo para ajustar-se a uma estrutura de teste, o que você realmente precisa é de um host ou ambiente equipado para erros. Existem várias maneiras de simular nossa lentidão na rede (mesmo as ferramentas de teste da Microsoft têm um pouco disso na área de testes na web). Tive maior sucesso ao colocar máquinas atrás de um roteador que pode ser adulterado para alterar simulações em coordenação com um conjunto de banco de dados para produzir erros e scripts para alterar os erros que o banco de dados produz.

Mesmo com isso, se você for rápido o bastante ou longe o suficiente em direção ao hardware, existem erros como problemas de simultaneidade e falhas de gravação atrasadas que praticamente não é possível simular. Às vezes, você precisa causá-las de verdade e outras vezes só precisa trabalhar sem a rede de segurança.

Conta
fonte
Concordo - em alguns casos, você não pode arcar com os custos indiretos da injeção de dependência no seu código de versão, por exemplo. Não é uma questão cotidiana, mas pode acontecer.
21311 Steve #