Como testar métodos privados de teste de unidade no MS Test
Antes de começarmos a ver, como um método privado pode ser testado por unidade usando o MS Test? Vamos discutir se é uma boa ideia testar um método privado ou não?
Muitas vezes eu vi que existem duas escolas de pensamentos,
- Métodos privados devem ser testados.
- Métodos privados não devem ser testados.
Para colocar essas coisas em perspectiva, vamos considerar uma classe salarial do sistema em teste (SUT), conforme mostrado na lista abaixo.
namespace Calculator
{
public class Salary
{
public int CalculateSal(int bs, int nwd)
{
int ts ;
if(isValidNwd(nwd))
{
ts= bs*nwd;
}
else
{
ts = 1000;
}
return ts;
}
private bool isValidNwd(int nwd)
{
if (nwd > 8)
{
return true;
}
else
{
return false;
}
}
}
}
Um sistema em teste Classe salarial tem duas funções:
- O método CalculateSal é um método público e são necessários dois parâmetros para calcular o salário
- O método isValidwd é um método privado e usa um parâmetro. Essa função retorna true se o número de dias úteis for maior que 8, ou então retorna false.
- O método CalculateSal primeiro verifica se o número de dias úteis é válido ou não usando o método privado isValidWd.
- Se o número de dias úteis for válido, o salário é calculado pela multiplicação do salário base e do número de dias úteis, ou então é fixado em $ 1000.
Agora temos um sistema em teste Classe salarial com duas funções.

Uma opinião é que o método privado não deve ser testado separadamente. Isso ocorre porque o método privado é usado dentro do método público e quando testamos o comportamento do método público, o comportamento do método privado também é testado.
Outra opinião é que o método privado deve ser testado por unidade quanto ao seu próprio comportamento isoladamente com os outros métodos públicos ou privados. Antes de prosseguirmos e vermos como testar um método privado, vamos pensar um pouco se existe outra maneira possível de contornar isso.
Violating Single Responsibility Principle
Atualmente, o sistema em teste Classe salarial está violando o Princípio de Responsabilidade Única porque tem duas responsabilidades:
- Para calcular o salário (método público)
- Para validar o número de dias úteis (método privado)

Não podemos ter certeza de uma boa cobertura de código da classe SUT Salário, a menos que testemos o comportamento de validação de dias úteis da classe e seja privado por design. Uma boa opção poderia ser esta: ao criar a classe Salário, podemos dividir as responsabilidades em duas classes separadas com métodos públicos para calcular o salário e validar os dias úteis. Podemos então escrever testes unitários para métodos públicos de ambas as classes. Vamos ver como fazer isso.
Escrevendo teste de unidade para métodos privados
Se você é da opinião de que um método privado na classe SUT deve ser testado, então você tem duas opções:
- Use refatoração - mas isso é um pouco complexo;
- Use a classe VSTS PrivateObject– isso é simples!

Vamos ver como podemos usar uma classe PrivateObject para testar a unidade de um método privado. Para usar uma classe de objeto privado, você precisa:
- Adicione uma referência de Microsoft.VisualStudio.QualityTools.UnitTestFramework no projeto de teste. Se você criou o projeto selecionando o modelo do projeto de teste de unidade, essa referência será adicionada por padrão no projeto.
- Add a namespace Microsoft.VisualStudio.TestTools.UnitTesting.
O construtor de PrivateObjectClass usa o tipo como parâmetro, portanto, aqui você precisará passar o tipo da classe SUT Salary e, em seguida, no objeto de PrivateObjectClass, chamar o método invoke para invocar o método private.
Podemos testar o método privado isValidNwd conforme mostrado na listagem abaixo:
[TestMethod]
public void ReturnTrueForValidWorkingDays() {
PrivateObject objToTestPrivateMethod=new PrivateObject(typeof(Salary));
bool result=Convert.ToBoolean(objToTestPrivateMethod.Invoke("isValidNwd", 6));
Assert.AreEqual(result, true);
}
Essencialmente, estamos realizando as seguintes tarefas:
· Criando um objeto da classe PrivateObject
· Passando um tipo de classe Salary como um parâmetro de entrada no construtor
· Usando o método invoke para executar o método privado da classe SUT Salary
· Passando dois parâmetros no método invoke: o primeiro parâmetro é o nome do método privado e o segundo parâmetro é o argumento que será passado para o método privado durante a execução
E é assim que podemos testar a unidade de um método privado!
Conclusão
Neste post aprendemos sobre:
- Testar um método privado ou não
- Como testar o método privado usando a classe PrivateObject
Espero que este post seja útil para você - obrigado por ler. Boa codificação!
