Я использую платформу XUnit для тестирования своего кода C #.
Есть ли в этой структуре доступный метод assert, который выполняет сравнение объектов? Я намерен проверить равенство всех публичных и частных переменных-членов объекта.
Я пробовал эти альтернативы, но они редко срабатывают:
1) bool IsEqual = (Obj1 == Obj2)
2) Assert.Same(Obj1, Obj2) which I couldnt understand what happens internally
В xUnit есть глубокое сравнение. Вам нужно будет реализовать IEquatable ‹T› для своих объектов, и тогда Assert.Equals будет работать. seldary 21.06.2012
Assert.Same() сравнивает по ссылке; он утверждает, что Obj1 и Obj2 являются одним и тем же объектом, а не просто выглядят одинаково. TeaDrivenDev 12.05.2014
Для этого вам понадобится настраиваемый компаратор, когда вы сравниваете объекты, в противном случае они проверяются на основе того, ссылаются ли они на один и тот же объект в памяти. Чтобы переопределить это поведение, вам нужно переопределить методы Equals и GetHashCode, а затем вы можете сделать:
Assert.True(obj1.Equals(obj2));
Вот страница MSDN с перегрузкой метода Equals abt: http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
Также добавьте комментарий к вопросу: В чем разница между IEquatable и просто переопределить Object.Equals ()?
Ответ 2 · рейтинг 79 · The Integrator
У меня была аналогичная проблема, но, к счастью, я уже использую
using Newtonsoft.Json;
Поэтому мне просто нужно было сериализовать его в объект json, а затем сравнить как строку.
var obj1Str = JsonConvert.SerializeObject(obj1);
var obj2Str = JsonConvert.SerializeObject(obj2);
Assert.Equal(obj1Str, obj2Str );
Ответ 3 · рейтинг 18 · Adrian Petrescu
Библиотека FluentAssertions имеет внутри довольно мощную логику сравнения.
[Fact]
public void RetrievingACustomer_ShouldReturnTheExpectedCustomer()
{
// Arrange
var expectedCustomer = new Customer
{
FirstName = "Silence",
LastName = "Dogood",
Address = new Address
{
AddressLineOne = "The New-England Courant",
AddressLineTwo = "3 Queen Street",
City = "Boston",
State = "MA",
PostalCode = "02114"
}
}.ToExpectedObject();
// Act
var actualCustomer = new CustomerService().GetCustomerByName("Silence", "Dogood");
// Assert
expectedCustomer.ShouldEqual(actualCustomer);
}
Ответ 5 · рейтинг 9 · Engineer_Andrew
Я знаю, что это старый вопрос, но поскольку я наткнулся на него, я подумал, что взвесу новое доступное решение (по крайней мере, в xunit 2.3.1 в решении .net Core 2.0).
Я не уверен, когда это было введено, но теперь существует перегруженная форма .Equal, которая принимает экземпляр IEqualityComparer<T> в качестве третьего параметра. Вы можете создать собственный компаратор в своем модульном тесте, не загрязняя им свой код.
Следующий код можно вызвать следующим образом: Assert.Equal(expectedParameters, parameters, new CustomComparer<ParameterValue>());
Похоже, что XUnit по умолчанию прекращает обработку теста, как только обнаруживается сбой, поэтому запуск нового EqualException из нашего компаратора, похоже, соответствует тому, как XUnit работает из коробки.
public class CustomComparer<T> : IEqualityComparer<T>
{
public bool Equals(T expected, T actual)
{
var props = typeof(T).GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in props)
{
var expectedValue = prop.GetValue(expected, null);
var actualValue = prop.GetValue(actual, null);
if (!expectedValue.Equals(actualValue))
{
throw new EqualException($"A value of \"{expectedValue}\" for property \"{prop.Name}\"",
$"A value of \"{actualValue}\" for property \"{prop.Name}\"");
}
}
return true;
}
public int GetHashCode(T parameterValue)
{
return Tuple.Create(parameterValue).GetHashCode();
}
}
Изменить: я обнаружил, что сравнение фактических и ожидаемых значений с != не было эффективным для определенных типов (я уверен, что есть лучшее объяснение, связанное с различием между ссылочными типами и типами значений, но это не на сегодня). Я обновил код, чтобы использовать метод .Equals для сравнения двух значений, и, похоже, он работает намного лучше.