Pergunta

Eu tenho uma classe que eu sou o teste de unidade para com DUnit. Tem uma série de métodos de alguns métodos públicos e métodos privados.

type
  TAuth = class(TDataModule)
  private
    procedure PrivateMethod;
  public
    procedure PublicMethod;
  end;

Para escrever um teste de unidade para esta classe I tem que fazer todo o público métodos.

Existe uma maneira diferente de declarar os métodos privados de modo que eu ainda pode testá-los, mas eles não são públicos?

Foi útil?

Solução

Você não precisa torná-los públicos. Protegido vai fazer. Então você pode subtipo da classe para testes de unidade ea superfície de métodos protegidos. Exemplo:

type
  TAuth = class(TDataModule)
  protected
    procedure MethodIWantToUnitTest;
  public
    procedure PublicMethod;
  end;

Agora você pode subtipo-lo para o teste de unidade:

interface

uses
  TestFramework, Classes, AuthDM;

type
  // Test methods for class TAuthDM
  TestAuthDM = class(TTestCase)
     // stuff
  end;

  TAuthDMTester = class(TAuthDM)
  public
    procedure MethodIWantToUnitTestMadePublic;
  end;

implementation

procedure TAuthDMTester.MethodIWantToUnitTestMadePublic;
begin
  MethodIWantToUnitTest;
end;

No entanto, se os métodos que pretende testar unidade estão fazendo coisas tão intimamente com o módulo de dados que não é seguro ter-lhes qualquer coisa, mas privado, então você deve realmente considerar refatoração os métodos, a fim de separar o código que necessidades para ser testada unidade e o código que acede as entranhas do módulo de dados.

Outras dicas

É um pouco hacky, mas eu acho que essa é a abordagem mais simples e mais clara. Utilize essa diretriz compilação condicional:

  {$IfNDef TEST}
  private
  {$EndIf}

Seu projeto de teste de unidade deve definir TEST em project → conditional defines. Sem uma especificação visibilidade, tornam-se publicado.

Cuidado: se a visibilidade privada não é o primeiro na declaração da classe, ele irá obter a definição anterior. A maneira mais segura, mas mais detalhado e menos claro, seria:

  private
  {$IfDef TEST}
  public
  {$EndIf}

Isto tem uma série de vantagens sobre a criação de subclasses ou outras abordagens:

  • Não complexidade extra:. Há aulas extras em seu código
  • Ninguém pode "erroneamente" subclasse e substituir sua classe:. Você preserva sua arquitetura
  • Quando você diz um método estiver protegido, um pouco de esperar que ele será substituído. Você está dizendo isso para quem está lendo seu código. Um método protegido que não deve ser substituído irá confundir seus leitores de código, quebrando meu princípio primeira programação: "Código deve ser escrito para ser lido por outros seres humanos"
  • DUnit está em sua própria unidade, não incluído em todos os lugares.
  • Você não toque confuso RTTI.

Eu acho que é uma solução mais clara, e melhor do que a resposta selecionada.

Quando eu usar isto, eu também configurar o projeto de teste para colocar os objetos de construção em um diretório diferente do projeto principal. Isso evita que os binários com a directiva TEST para misturar com outro código.

Eu recomendo os "Padrões xUnit teste " livro de Gerard Meszaros:

Test-Specific subclasse

Pergunta : Como podemos tornar o código testáveis ??quando precisamos de acesso Estado privada do SUT?

Resposta : Adicionar métodos que expõem a estado ou comportamento necessários pelo teste a uma subclasse do SUT.

... Se o sistema em teste (SUT) não foi concebidos especificamente para ser testada, podemos achar que o teste não pode obter acesso ao Estado que deve inicializar ou verificar em algum momento de o teste.

O artigo também explica quando usá-lo e quais os riscos que ela carrega.

Coloque o código DUnit dentro de sua unidade. Você pode acessar qualquer coisa que você gosta.

Em geral, quando eu chegar nesta situação, muitas vezes eu percebo que eu estou violando o princípio da responsabilidade individual. Claro que eu não sei nada sobre o seu caso específico, mas talvez, que os métodos privados devem estar em sua própria classe. O TAuth teria que ter uma referência para essa nova classe na seção privada, de.

Com RTTI Extensão (Delphi 2010 e mais recente), invocando métodos privados via RTTI é outra opção. Esta solução é também a resposta mais votadas em Como faço para testar uma classe que tem métodos privados, campos ou classes internas?

{$IFNDEF UNITEST}
private
{$ENDIF}

Uma solução simples, que dificilmente é um hack. Eu freqüentemente precisa testar métodos privados e esta técnica acrescenta tão pouco complicação possível.

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