Я ищу элегантное выражение, чтобы проверить, содержит ли перечислимое «подмножество» самого себя.
Позвольте мне проиллюстрировать на примере:
[Fact]
public void Test1()
{
// Arrange
var expected = new[]
{
new {F1 = 1, F2 = "1" },
new {F1 = 2, F2 = "2" },
};
// Act
var actual = new[]
{
new {F1 = 1, F2 = "1", F3 = true },
new {F1 = 2, F2 = "2", F3 = true },
new {F1 = 3, F2 = "3", F3 = true },
};
// Assert
actual
.Should()
.LookingForFluentAssertionsExpression( //<-- I'm looking for this part
expected,
options => options.SomeOptions(),
because: "expected is a 'subset' of actual"
);
}
Я безуспешно пробовал Сравнение графов объектов:
// Assert
actual
.Should()
.BeEquivalentTo(expected, o => o.ExcludingMissingMembers());
Ожидается, что фактически будет коллекция с 2 элементами, но {{F1 = 1, F2 = 1, F3 = True}, {F1 = 2, F2 = 2, F3 = True}, {F1 = 3, F2 = 3, F3 = Истина }}"
"содержит на 1 элемент больше, чем"
{{F1 = 1, F2 = 1}, {F1 = 2, F2 = 2}}.
Очевидно, я могу сделать:
// Assert
actual
.Where(a => expected.Any(e=>e.F1 == a.F1 && e.F2 == a.F2))
.Should()
.BeEquivalentTo(expected, o => o.ExcludingMissingMembers());
но выглядит немного грязно.
Другой вариант:
// Assert
expected
.ToList()
.ForEach(expectedItem =>
actual
.Should()
.ContainEquivalentOf(
expectation: expectedItem,
config: o => o.ExcludingMissingMembers())
);
// Or the same without Linq:
//
//foreach (var expectedItem in expected)
//{
// actual
// .Should()
// .ContainEquivalentOf(
// expectation: expectedItem,
// config: o => o.ExcludingMissingMembers());
//}
но вообще не читается.
Привет @panoskarajohn, спасибо за твой комментарий. Это всего лишь «минимально воспроизводимый образец». В моем сценарии переопределение Equals нецелесообразно. Помните, что у FluentAssertions есть методы для проверки графов объектов (<- я только что обновил свой вопрос, чтобы поговорить о сравнении графов объектов)
Вставьте actual
в HashSet<>
. После этого вы можете вызвать actualHashSet.IsSupersetOf(expected)
. Имейте в виду, что в зависимости от типа вы должны указать IEqualityComparer<T>
в ctor хеш-набора, но анонимные типы имеют семантику значений, поэтому в вашем примере это не нужно. Также вы можете сделать обратное и вызвать expectedHashSet.IsSubsetOf(actual)
, в зависимости от ваших потребностей.
@Oliver, большое спасибо за ваше предложение, можете ли вы уточнить его в ответе или в сути с небольшим количеством кода? Спасибо!
Вы можете использовать два вызова ContainEquivalentOf
, когда вы передаете элемент из коллекции expected
.
например
using (new AssertionScope())
{
actual.Should().ContainEquivalentOf(expected[0]);
actual.Should().ContainEquivalentOf(expected[1]);
}
И не надо ExcludingMissingMembers
. FA будет ожидать только те свойства, которые вы определили в соответствии с вашими ожиданиями.
Не могли бы вы уточнить немного кода, пожалуйста?
Выглядит хорошо для нескольких предметов. Спасибо
Что вы об этом думаете: stackoverflow.com/a/75296827/842935
Выглядит слишком сложным для меня. Простая петля тоже сработала бы. Вы даже можете обернуть этот цикл в AssertionScope
, как в моем примере.
В конце я закодировал его, используя ClassData. Я не знаю, лучшее ли это решение, я публикую его здесь с другими ответами. Не стесняйтесь критиковать этот ответ. Мы здесь, чтобы учиться.
public class CalculatorTestData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] { new { F1 = 1, F2 = "1" }, "reason 1" };
yield return new object[] { new { F1 = 2, F2 = "2" }, "reason 2" };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
[Theory]
[ClassData(typeof(CalculatorTestData))]
public void Test2(object expected, string because)
{
// Arrange
// Act
var actual = new[]
{
new {F1 = 1, F2 = "1", F3 = true },
new {F1 = 2, F2 = "2", F3 = true },
new {F1 = 3, F2 = "3", F3 = true },
};
// Assert
actual
.Should()
.ContainEquivalentOf(
expectation: expected,
because: because);
}
Вопрос немного вводит в заблуждение, вот какой был бы ответ, если бы вы действительно хотели протестировать подмножество: stackoverflow.com/questions/3274541/…. Ну, я вижу проблему с вашим кодом, вы используете анонимные объекты, которые, когда дело доходит до равенства, вы проверяете ссылку на объект. Я бы предложил использовать реальный объект и переопределить функцию Equals.