Xunit.Assert.Collection中的问题 - C#

问题描述 投票:8回答:2

我有一个类库,它包含以下模型和方法

模型:

public class Employee {
    public int EmpId { get; set; }
    public string Name { get; set; }
}

方法:

public class EmployeeService {
    public List<Employee> GetEmployee() {
        return new List<Employee>() {
            new Employee() { EmpId = 1, Name = "John" },
            new Employee() { EmpId = 2, Name = "Albert John" },
            new Employee() { EmpId = 3, Name = "Emma" },
        }.Where(m => m.Name.Contains("John")).ToList();
    }
}

我有一个测试方法

[TestMethod()]
public void GetEmployeeTest() {
    EmployeeService obj = new EmployeeService();
    var result = obj.GetEmployee();
    Xunit.Assert.Collection<Employee>(result, m => Xunit.Assert.Contains("John",m.Name));
}

我收到了一条Exception消息

Assert.Collection() Failure
Collection: [Employee { EmpId = 1, Name = "John" }, Employee { EmpId = 2, Name = "Albert John" }]
Expected item count: 1
Actual item count:   2

我的要求是检查所有items.Name应该包含子字符串“John”。请帮助我如何检查使用Xunit.Assert.Collection

c# unit-testing collections assert xunit
2个回答
27
投票

似乎Assert.Collection只使用每个元素检查器一次。因此,对于您的测试,以下工作:

如果序列result恰好有两个元素:

[Fact]
public void GetEmployeeTest()
{
    EmployeeService obj = new EmployeeService();
    var result = obj.GetEmployee();

    Assert.Collection(result, item => Assert.Contains("John", item.Name),
                              item => Assert.Contains("John", item.Name));
}

如果有很多元素,请将Assert更改为

Assert.All(result, item => Assert.Contains("John", item.Name));

应该给你你期望的结果。


2
投票

对于那些对集合中物品顺序不感兴趣的人来说,这是对Ayb4btu的answer的扩展。

以下方法基于原始XUnit实现,并允许您使用非常类似的接口进行测试:

public static class TestExpect
{
public static void CollectionContainsOnlyExpectedElements<T>(IEnumerable<T> collectionToTest, params Func<T, bool>[] inspectors)
{
    int expectedLength = inspectors.Length;
    T[] actual = collectionToTest.ToArray();
    int actualLength = actual.Length;

    if (actualLength != expectedLength)
        throw new CollectionException(collectionToTest, expectedLength, actualLength);

    List<Func<T, bool>> allInspectors = new List<Func<T, bool>>(inspectors);
    int index = -1;
    foreach (T elementToTest in actual)
    {
        try
        {
            index++;
            Func<T, bool> elementInspectorToRemove = null;
            foreach (Func<T, bool> elementInspector in allInspectors)
            {
                if (elementInspector.Invoke(elementToTest))
                {
                    elementInspectorToRemove = elementInspector;
                    break;
                }
            }

            if (elementInspectorToRemove != null)
                allInspectors.Remove(elementInspectorToRemove);
            else
                throw new CollectionException(collectionToTest, expectedLength, actualLength, index);
        }
        catch (Exception ex)
        {
            throw new CollectionException(collectionToTest, expectedLength, actualLength, index, ex);
        }
    }
}
}

这里的区别在于集合

 string[] collectionToTest = { "Bob", "Kate" };

以下几行都不会产生CollectionException

 TestExpect.CollectionContainsOnlyExpectedElements(collectionToTest, x => x.Equals("Bob"), x => x.Equals("Kate"));
 TestExpect.CollectionContainsOnlyExpectedElements(collectionToTest, x => x.Equals("Kate"), x => x.Equals("Bob"));

而使用Assert.Collection - 只有上述两行中的第一行才能正常工作,因为按顺序评估了检查员的集合。

使用此方法可能会对性能产生影响,但如果您只测试相当小的集合(因为您可能会进行单元测试),您将永远不会注意到这种差异。

© www.soinside.com 2019 - 2024. All rights reserved.