Pergunta

Eu estou perto do início de um novo projeto e (surpresa!) Para a primeira vez que estou tentando incluir testes de unidade em um projeto meu.

Estou tendo problemas para conceber alguns dos testes de unidade em si. Eu tenho alguns métodos que têm sido fácil o suficiente para teste (passe em dois valores e verificar se há uma saída esperada). Eu tenho outras partes do código que está fazendo as coisas mais complexas como a execução de consultas no banco de dados e eu não tenho certeza de como testá-los.

public DataTable ExecuteQuery(SqlConnection ActiveConnection, string Query, SqlParameterCollection Parameters)
{
    DataTable resultSet = new DataTable();
    SqlCommand queryCommand = new SqlCommand();
    try
    {
        queryCommand.Connection = ActiveConnection;
        queryCommand.CommandText = Query;

        if (Parameters != null)
        {
            foreach (SqlParameter param in Parameters)
            {
                 queryCommand.Parameters.Add(param);
            }
        }

        SqlDataAdapter queryDA = new SqlDataAdapter(queryCommand);
        queryDA.Fill(resultSet);
    }
    catch (Exception ex)
    {
        //TODO: Improve error handling
        Console.WriteLine(ex.Message);
    }

    return resultSet;
}

Este método leva essencialmente em todos os bits e peças necessárias para extrair alguns dados do banco de dados e retorna os dados em um objeto DataTable.

A primeira pergunta é provavelmente o mais complexo:? O que devo mesmo teste em uma situação como esta

Uma vez que está resolvido, vem a questão da existência ou não para zombar fora os componentes de banco de dados ou tentar teste contra o DB real.

Foi útil?

Solução

O que você está testando?

Existem três possibilidades, em cima da minha cabeça:

A. Você está testando a classe DAO (acesso objeto de dados), certificando-se de que está corretamente empacotamento os valores / parâmetros sendo passados ??para o banco de dados ,, e corretamente empacotamento / transformação / embalagem resultados obtidos frm o banco de dados.

Neste caso, você não precisa se conectar ao banco de dados em tudo; só precisa de um teste de unidade que substitui a base de dados (ou camada intermédia, por exemplo., JDBC, (N) de hibernação, iBatis) com uma simulação.

B. Você está testando a correção sintática de SQL (gerado).

Neste caso, porque dialetos SQL diferentes, você deseja executar o SQL (possivelmente gerado) contra a versão correta do seu RDBMS, em vez de tentar ridicularizar todos os caprichos de seus RDBMS (e de modo que qualquer atualização de RDBMS que a funcionalidade mudança são capturados por seus testes).

C. Você está testando o semântica justeza do seu SQL, ou seja, que para um determinado conjunto de dados de base, suas operações (acessos / seleciona e mutações / inserções e atualizações) produzir o novo conjunto de dados esperado.

Para isso, você quer usar algo como dbunit (que permite a criação de uma linha de base e comparar um conjunto de resultados para um conjunto de resultado esperado), ou, eventualmente, fazer o seu teste inteiramente na base de dados, utilizando o contorno técnica que eu aqui :. melhor maneira de testar SQL queries

Outras dicas

É por isso que testes de unidade (IMHO) às vezes pode criar uma falsa sensação de segurança por parte dos desenvolvedores. Na minha experiência com aplicativos que falar com um banco de dados, os erros são geralmente o resultado de ser dados em um estado inesperado (incomum ou valores em falta etc.). Se você costuma zombar de acesso a dados em seus testes de unidade, você acha que seu código está funcionando muito bem quando na verdade é ainda vulnerável a esse tipo de erro.

Eu acho que a melhor abordagem é ter um banco de dados de teste prático, repleto de rios de dados de baixa qualidade, e executar os testes de componentes de banco de dados contra isso. Durante todo o tempo lembrando que seus usuários será muito, muito melhor do que você está em estragar seus dados.

O ponto inteiro de um teste de unidade é a testar uma unidade (duh) isoladamente. O ponto inteiro de uma chamada de banco de dados é integrar com outra unidade (banco de dados). Ergo:. Não faz sentido para as chamadas de banco de dados de teste de unidade

Você deve, no entanto, chamadas de banco de dados de teste de integração (e você pode usar as mesmas ferramentas que você usa para testes de unidade se você quiser).

Pelo amor de Deus, não testar contra um banco de dados ao vivo, já povoada. Mas você sabia disso.

Em geral, você já tem uma idéia de que tipo de dados cada consulta vai recuperar, se você é autenticar usuários, olhando para cima agenda / org entradas de gráfico, ou o que quer. Você sabe quais campos você está interessado, e você sabe o que existem restrições sobre eles (por exemplo, UNIQUE, NOT NULL, e assim por diante). Você está unidade testar o seu código que interage com o banco de dados, e não o próprio banco de dados, assim que pensar em termos de como testar essas funções. Se é possível para um campo a ser NULL, você deve ter um teste que garante que seus punhos do código NULL valores corretamente. Se um de seus campos é uma string (CHAR, VARCHAR, TEXT, & c), teste para ter certeza que você está lidando com caracteres de escape corretamente.

Suponha que os usuários vão tentar colocar qualquer coisa * no banco de dados, e gerar casos de teste em conformidade. Você vai querer usar objetos mock para isso.

* Inclui entrada indesejável, malicioso ou inválido.

Você pode testar tudo unidade, exceto: queryDA.Fill(resultSet);

Assim que você executar queryDA.Fill(resultSet), você quer ter a zombar / fake o banco de dados, ou você está fazendo testes de integração.

Eu, pelo menos, não vejo testes de integração como sendo ruim, é apenas que ele vai pegar um tipo diferente de erro, tem diferentes chances de falsos negativos e falsos positivos, não é susceptível de ser feito muito frequentemente porque é tão lento.

Se eu estivesse unidade testar este código, eu seria validar que os parâmetros são construídos corretamente, se o comando construtor de criar o número certo de parâmetros? Será que eles têm um valor? Fazer nulos, cadeias vazias e DbNull get tratados corretamente?

Na verdade, enchendo o conjunto de dados está testando seu banco de dados, que é um fora componente escamosa do escopo do seu DAL.

A rigor, um teste que escreve / lê a partir de um banco de dados ou um sistema de arquivos não é um teste de unidade. (Embora possa ser um teste de integração e que pode ser escrito usando NUnit ou JUnit). Unidade-testes são supostos para operações de teste de uma única classe, isolando as suas dependências. Então, quando você escreve unidade-teste para as camadas de interface e business-lógica, você deve não precisa de um banco de dados.

OK, mas como você unidade-teste da camada de acesso a banco de dados

? Eu como os conselhos deste livro: Padrões xUnit teste (os pontos link para o livro de "Testing w / DB" capítulo As teclas são:.

  • usar testes de ida e volta
  • não escrever muitos testes em sua instalação de ensaio acesso a dados, porque eles vão correr muito mais lento do que os testes de unidade "reais"
  • Se você pode evitar o teste com um banco de dados real, teste sem um banco de dados

Para testes de unidade I geralmente zombam ou falso banco de dados. Em seguida, use a sua simulação ou implementação falso via injeção de dependência para testar seu método. Você também provavelmente têm alguns testes de integração que irão testar restrições, relações de chave estrangeira, etc. no seu banco de dados.

Quanto ao que você iria testar, você certificar-se de que o método está usando a conexão a partir dos parâmetros, que a string de consulta é atribuída ao comando, e que o seu conjunto de resultados retornado é o mesmo que você está fornecendo através de uma expectativa sobre o método de preenchimento. Nota - é provavelmente mais fácil de testar um método GET que retorna um valor de um método de preenchimento dos modifica um parâmetro

.

Para fazer isso corretamente, embora você deve usar algum injeção de dependência (DI), e para .NET existem vários. Atualmente, estou usando o Framework Unity, mas há outros que são mais fáceis.

Aqui está um link de site sobre este assunto, mas há outros: Injeção Dependência em .NET com exemplos?

Isso permitirá que você para zombar mais facilmente a outras partes da sua aplicação, por ter apenas uma classe falsa implementar a interface, para que possa controlar a forma como ele irá responder. Mas, isso também significa projetar a uma interface.

Uma vez que você perguntou sobre as melhores práticas isso seria um, IMO.

Então, não vai para o db a menos que você precisa, como sugerido é outra.

Se você precisa testar certos comportamentos, tais como relações de chave estrangeira com exclusão em cascata, então você pode querer testes de banco de dados de escrita para isso, mas geralmente não ir a um banco de dados real é melhor, esp desde mais de uma pessoa pode executar um teste de unidade em um tempo e se eles estão indo para os mesmos testes de banco de dados pode falhar como os dados esperados podem mudar.

Edit: Por teste de unidade de banco de dados que eu quero dizer isso, como ele é projetado para usar apenas T-SQL para fazer alguma configuração, teste e desmontagem. http://msdn.microsoft.com/en- us / library / aa833233% 28VS.80% 29.aspx

Em JDBC projeto baseado, conexão JDBC pode ser ridicularizado, de modo que os testes podem ser executados sem RDBMS ao vivo, com cada caso de teste isolado (sem conflito de dados).

Ele permite verificar, persistência código passa adequadas consultas / parâmetros (por exemplo, https://github.com/playframework/playframework/blob/master/framework/src/anorm/src/test/scala/anorm/ParameterSpec.scala ) e lidar com resultados JDBC (análise / mapeamento) como esperado ( "leva em todos os bits necessários e peças para extrair alguns dados do banco de dados e retorna os dados em um objeto DataTable").

Framework como jOOQ ou o meu Acolyte estrutura pode ser usada para: https://github.com/cchantep/acolyte .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top