Acessando membros internos através System.Reflection?
-
05-07-2019 - |
Pergunta
Eu estou tentando unidade de teste uma classe que tem muitas funções internas. Estes, obviamente, precisam testar também, mas meu projeto testes é independente, principalmente porque abrange muitos projetos pequenos, relacionados. O que eu tenho até agora é:
FieldInfo[] _fields =
typeof(ButtonedForm.TitleButton).GetFields(
BindingFlags.NonPublic | BindingFlags.Instance |
BindingFlags.DeclaredOnly);
Console.WriteLine("{0} fields:", _fields.Length);
foreach (FieldInfo fi in _fields)
{
Console.WriteLine(fi.Name);
}
Este cospe todos os membros privados bem, mas ainda não exibe internos. Eu sei que isso é possível, porque quando eu estava brincando com os testes Autogenerated que Visual Studio pode produzir, ele perguntou sobre algo a ver com a exibição internos ao projeto de teste. Bem, agora eu estou usando NUnit e realmente gostando, mas como eu posso conseguir a mesma coisa com ele?
Solução
Seria mais apropriado utilizar a InternalsVisibleTo
atributo para conceder acesso aos membros internos da montagem para a sua unidade de teste de montagem.
Aqui está um link com alguns útil informações adicionais e uma caminhada através de:
Para realmente responder sua pergunta ... Interno e protegida não são reconhecidos na API .NET Reflexão. Aqui está uma citação de MSDN :
Os C # palavras-chave protegidas e internos não têm significado em IL e não são usados ??nas APIs reflexão. Os termos correspondentes na IL somos família e Montagem. Para identificar um método interno usando Reflexo, utilizar o IsAssembly propriedade. Para identificar um método interno protegido, utilizar o IsFamilyOrAssembly .
Outras dicas
Adicionando o href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx" atributo rel="noreferrer"> InternalsVisibleTo nível de montagem
Por exemplo, adicione o seguinte ao seu assembly fora de qualquer classe: Ou para uma segmentação mais específica: Note, se sua aplicação assembly tem um nome forte, o teste de montagem também terá de ser fortemente nomeado. [assembly: InternalsVisibleTo("AssemblyB")]
[assembly:InternalsVisibleTo("AssemblyB, PublicKey=32ab4ba45e0a69a1")]
Eu acho que você precisa se perguntar se você deve escrever testes de unidade para métodos privados? Não se você escrever testes de unidade para os seus métodos públicos, com uma cobertura de código 'razoável', você já está testando quaisquer métodos privados que precisam ser chamado como resultado?
Amarrando testes para métodos privados vão fazer os testes mais frágil. Você deve ser capaz de alterar a implementação de quaisquer métodos privados sem quebrar quaisquer testes.
Refs:
http://weblogs.asp.net/tgraham/ Arquivo / 2003/12/31 / 46984.aspx http://richardsbraindump.blogspot.com/2008 /08/should-i-unit-test-private-methods.html http://junit.sourceforge.net/doc/faq/faq.htm#tests_11 http://geekswithblogs.net/geekusconlivus/archive/2006/07/13 /85088.aspx
O código só é mostrando campos - assim que eu espero que não iria mostrar quaisquer membros internos, como campos devem sempre ser privado IMO. (Com a possível excepção das constantes).
O ButtonedForm.TitleButton realmente tem quaisquer campos não privados? Se você está tentando encontrar internos métodos então, obviamente, você precisa estar chamando GetMethods
(ou GetMembers
) para chegar a eles.
Como já foi sugerido, InternalsVisibleTo
é muito útil para testar (e quase exclusivamente para testar!). Quanto a saber se você deve estar testando métodos internos - Eu certamente achar que é útil para ser capaz de fazê-lo. Não considero o teste de unidade como sendo exclusivamente caixa-preta do teste. Muitas vezes, quando você sabe que a funcionalidade pública é implementado usando alguns métodos internos conectados em uma maneira simples, é mais fácil fazer o teste completo de cada um dos métodos internos e alguns testes "pseudo-integração" no método público.
A justificação para a utilização do InternalsVisible está sob minhas circunstâncias. Nós compramos o código fonte para um gráfico de controle. Descobrimos onde precisamos fazer algumas modificações para que o controle da fonte e compilar a nossa própria versão. Agora, para garantir que não quebrar nada, existem alguns testes de unidade Eu preciso escrever que necessitem de acesso a alguns campos internos.
Este é um caso perfeito onde o InternalsVisible faz sentido.
Eu estava pensando, porém, o que você faz se você não tem acesso à fonte? Como você pode chegar a um campo interno? .Net reflector pode ver que o código, mas eu acho que é apenas olhando para o IL.