Quando estamos realizando testes unitários, pode ser necessário comparar a igualdade de atributos em vez da igualdade de referência entre duas instâncias de objetos. No entanto, a comparação manual de cada campo com os valores esperados em outro objeto pode não ser viável. Felizmente, existem algumas abordagens que podemos utilizar para realizar essa comparação de forma mais eficiente.
Opção 1: Utilizar uma Extensão de Terceiros
Uma opção é utilizar uma extensão de terceiros, como o Fluent Assertions, que fornece métodos de comparação mais expressivos e configuráveis. Com o Fluent Assertions, podemos utilizar o método .ShouldBeEquivalentTo()
para verificar se dois objetos são equivalentes em termos de atributos, ignorando o tipo dos objetos e considerando apenas os nomes das propriedades e seus valores.
Aqui está um exemplo de como utilizar o método .ShouldBeEquivalentTo()
do Fluent Assertions:
actual.ShouldBeEquivalentTo(expected, options => options.ExcludingNestedObjects());
Nesse exemplo, estamos comparando os objetos actual
e expected
, excluindo a comparação de objetos aninhados. O método .ShouldBeEquivalentTo()
oferece várias opções de configuração, como a profundidade da recursão e a exclusão de membros que não correspondem.
Opção 2: Criar uma Função de Comparação Personalizada
Se preferirmos não depender de uma extensão de terceiros, podemos criar nossa própria função de comparação personalizada utilizando reflexão. Essa abordagem nos permite comparar os atributos de duas instâncias de objetos sem precisar modificar a implementação padrão de igualdade da classe em teste.
Aqui está um exemplo de como criar uma função de comparação personalizada utilizando reflexão:
public static bool PublicInstancePropertiesEqual<T>(T self, T to, params string[] ignore) where T : class
{
if (self != null && to != null)
{
var type = typeof(T);
var ignoreList = new List<string>(ignore);
var unequalProperties = from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
where !ignoreList.Contains(pi.Name)
let selfValue = type.GetProperty(pi.Name).GetValue(self, null)
let toValue = type.GetProperty(pi.Name).GetValue(to, null)
where selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue))
select selfValue;
return !unequalProperties.Any();
}
return self == to;
}
Nesse exemplo, estamos comparando os atributos públicos e de instância das classes self
e to
, ignorando os atributos especificados na lista ignore
. A função retorna true
se todos os atributos forem iguais e false
caso contrário.
Conclusão
Ao realizar testes unitários, pode ser necessário comparar a igualdade de atributos entre duas instâncias de objetos. Utilizando extensões de terceiros, como o Fluent Assertions, ou criando funções de comparação personalizadas, podemos realizar essa comparação de forma mais eficiente e expressiva. Essas abordagens nos permitem verificar se os atributos dos objetos são iguais sem modificar a implementação padrão de igualdade da classe em teste.
Lembre-se de adaptar essas abordagens de acordo com as necessidades específicas do seu projeto e sempre realizar testes para garantir a corretude das comparações.