O Visual Studio permite o teste de unidade de métodos particulares por meio de uma classe acessadora gerada automaticamente. Eu escrevi um teste de um método privado que é compilado com êxito, mas falha no tempo de execução. Uma versão bastante mínima do código e do teste é:
//in project MyProj
class TypeA
{
private List<TypeB> myList = new List<TypeB>();
private class TypeB
{
public TypeB()
{
}
}
public TypeA()
{
}
private void MyFunc()
{
//processing of myList that changes state of instance
}
}
//in project TestMyProj
public void MyFuncTest()
{
TypeA_Accessor target = new TypeA_Accessor();
//following line is the one that throws exception
target.myList.Add(new TypeA_Accessor.TypeB());
target.MyFunc();
//check changed state of target
}
O erro de tempo de execução é:
Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.
De acordo com o intellisense - e, portanto, acho que o destino do compilador - é do tipo TypeA_Accessor. Mas, em tempo de execução, é do tipo TypeA e, portanto, a adição da lista falha.
Existe alguma maneira de parar esse erro? Ou, talvez mais provável, que outros conselhos as outras pessoas têm (eu prevejo que talvez "não teste métodos privados" e "não teste de unidade manipule o estado dos objetos").
c#
unit-testing
junichiro
fonte
fonte
Respostas:
Sim, não teste métodos particulares .... A idéia de um teste de unidade é testar a unidade por sua 'API' pública.
Se você acha que precisa testar muito comportamento privado, provavelmente há uma nova 'classe' oculta dentro da classe que está tentando testar, extraia-a e teste-a por sua interface pública.
Um conselho / ferramenta de pensamento ... Há uma ideia de que nenhum método deve ser privado. Significando que todos os métodos devem viver em uma interface pública de um objeto ... se você sentir que precisa torná-lo privado, provavelmente viverá em outro objeto.
Esse conselho não funciona muito bem na prática, mas geralmente é um bom conselho, e muitas vezes leva as pessoas a decompor seus objetos em objetos menores.
fonte
Você pode usar a classe PrivateObject
fonte
“Não há nada chamado como padrão ou melhor prática, provavelmente são apenas opiniões populares”.
O mesmo vale para esta discussão também.
Tudo depende do que você acha que é uma unidade, se você acha que UNIT é uma classe, então você só acessará o método público. Se você acha que o UNIT é uma linha de código, o método privado não fará com que você se sinta culpado.
Se você deseja chamar métodos privados, pode usar a classe "PrivateObject" e chamar o método invoke. Você pode assistir a este vídeo detalhado do youtube ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ), que mostra como usar "PrivateObject" e também discute se o teste de métodos privados é lógico ou não.
fonte
Outro pensamento aqui é estender o teste para classes / métodos "internos", dando mais uma sensação de caixa branca desse teste. Você pode usar InternalsVisibleToAttribute na montagem para expô-los a módulos de teste de unidade separados.
Em combinação com a classe selada, você pode abordar esse encapsulamento de forma que o método de teste seja visível apenas a partir da montagem mais unida de seus métodos. Considere que o método protegido na classe selada é de fato privado.
E teste de unidade:
fonte
Uma maneira de testar métodos privados é através da reflexão. Isso também se aplica ao NUnit e ao XUnit:
fonte
call methods
estático e não estático ?Ermh ... Veio aqui exatamente com o mesmo problema: Teste um método privado simples , mas essencial . Depois de ler este tópico, parece ser "Eu quero fazer esse furo simples neste pedaço de metal simples e quero garantir que a qualidade atenda às especificações" e depois venha "Ok, isso não é fácil. Antes de tudo, não existe uma ferramenta adequada para fazer isso, mas você pode construir um observatório de ondas gravitacionais em seu jardim.Leia meu artigo em http://foobar.brigther-than-einstein.org/ Primeiro, é claro, você tem que participar de alguns cursos avançados de física quântica, então você precisa de toneladas de nitrogênio ultra-legal e, claro, meu livro disponível na Amazon "...
Em outras palavras...
Não, primeiras coisas primeiro.
Todo e qualquer método, seja ele privado, interno, protegido e público , deve ser testável. Tem que haver uma maneira de implementar esses testes sem demora, como foi apresentado aqui.
Por quê? Exatamente por causa das menções arquitetônicas feitas até agora por alguns colaboradores. Talvez uma simples reiteração dos princípios de software possa esclarecer alguns mal-entendidos.
Nesse caso, os suspeitos comuns são: OCP, SRP e, como sempre, KIS.
Mas espere um pouco. A idéia de disponibilizar tudo ao público é mais menos política e um tipo de atitude. Mas. Quando se trata de código, mesmo na Comunidade de Código Aberto, isso não é dogma. Em vez disso, "ocultar" algo é uma boa prática para facilitar a familiarização com uma determinada API. Você ocultaria, por exemplo, os cálculos básicos do seu bloco de construção de termômetro digital novo no mercado - não para ocultar a matemática por trás da curva real medida para curiosos leitores de código, mas para impedir que seu código se torne dependente de alguns, talvez de repente usuários importantes que não resistiram a usar seu código anteriormente privado, interno e protegido para implementar suas próprias idéias.
Do que estou falando?
É fácil proclamar a Era de Aquário ou o que é chamado hoje em dia, mas se meu sensor passar de 1,0 a 2,0, a implementação do Translate ... poderá mudar de uma equação linear simples que seja facilmente compreensível e "re utilizável "para todos, para um cálculo bastante sofisticado que usa análise ou o que quer que seja, e assim eu decifrava o código de outros. Por quê? Porque eles não entenderam os princípios básicos da codificação de software, nem mesmo o KIS.
Para resumir este conto de fadas: Precisamos de uma maneira simples de testar métodos privados - sem demora.
Primeiro: Feliz ano novo, pessoal!
Segundo: ensaie as lições do arquiteto.
Terceiro: o modificador "público" é religião, não uma solução.
fonte
Outra opção que não foi mencionada é apenas criar a classe de teste de unidade como filho do objeto que você está testando. Exemplo da NUnit:
Isso permitiria o teste fácil de métodos privados e protegidos (mas não herdados) e permitiria manter todos os seus testes separados do código real, para que você não estivesse implantando conjuntos de testes na produção. Mudar seus métodos privados para métodos protegidos seria aceitável em muitos objetos herdados, e é uma alteração bastante simples de fazer.
CONTUDO...
Embora essa seja uma abordagem interessante para resolver o problema de como testar métodos ocultos, não tenho certeza se defenderia que esta é a solução correta para o problema em todos os casos. Parece um pouco estranho testar um objeto internamente, e eu suspeito que possa haver alguns cenários em que essa abordagem exploda em você. (Objetos imutáveis, por exemplo, podem dificultar alguns testes).
Enquanto mencionei essa abordagem, sugeriria que essa é mais uma sugestão de brainstorm do que uma solução legítima. Tome com um grão de sal.
EDIT: Acho realmente hilário que as pessoas votem nesta resposta, pois descrevo isso explicitamente como uma má ideia. Isso significa que as pessoas estão concordando comigo? Estou tão confuso.....
fonte
Do livro Trabalhando Efetivamente com o Código Legado :
A maneira de corrigi-lo, de acordo com o autor, é criando uma nova classe e adicionando o método como
public
.O autor explica mais a fundo:
Portanto, dentro desses limites, sua única opção real é criar o método
public
, seja na atual ou em uma nova classe.fonte
TL; DR: Extrai o método privado para outra classe, teste nessa classe; leia mais sobre o princípio SRP (princípio de responsabilidade única)
Parece que você precisa extrair o
private
método para outra classe; nisso deveria serpublic
. Em vez de tentar testar oprivate
método, você deve testar opublic
método dessa outra classe.Temos o seguinte cenário:
Precisamos testar a lógica de
_someLogic
; mas parece queClass A
assume mais papel do que precisa (viola o princípio do SRP); basta refatorar em duas classesDesta forma,
someLogic
poderia ser teste em A2; em A1, basta criar um A2 falso e injetar no construtor para testar se A2 é chamado para a função nomeadasomeLogic
.fonte
No VS 2005/2008, você pode usar o acessador privado para testar o membro privado, mas esse caminho desapareceu na versão posterior do VS
fonte