使用Fluent assertions对Collection集合的断言,是非常方便的。
var collection = new[] { 1, 2, 5, 8 };
collection.Should().NotBeEmpty() //不是空集合
.And.HaveCount(4) // 并且必须有4个元素
.And.ContainInOrder(new[] { 2, 5 }) // 包含 2,5 并且是有序的, 2,5 换成 2,1 就会出错
.And.ContainItemsAssignableTo<int>(); // 元素可以被赋值成 int类型
collection.Should().Equal(new List<int> { 1, 2, 5, 8 }); // 判断是否相等,元素一样就可以
collection.Should().Equal(1, 2, 5, 8);
//元素是否相等,不管排序,这个我们是最常用的。
collection.Should().BeEquivalentTo(8, 2, 1, 5);
collection.Should().NotBeEquivalentTo(new[] { 8, 2, 3, 5 });
collection.Should().HaveCount(c => c > 3)
.And.OnlyHaveUniqueItems();//元素是否具有唯一性
// 个数超过3个
collection.Should().HaveCountGreaterThan(3);
// 个数超过或等于 4个
collection.Should().HaveCountGreaterOrEqualTo(4);
// 个数小于或等于 4个
collection.Should().HaveCountLessOrEqualTo(4);
// 个数小于 5个
collection.Should().HaveCountLessThan(5);
// 个数不是3个
collection.Should().NotHaveCount(3);
// 跟另一个集合比对有相同个数
collection.Should().HaveSameCount(new[] { 6, 2, 0, 5 });
// 跟另一个集合比对有不同的个数
collection.Should().NotHaveSameCount(new[] { 6, 2, 0 });
// 第一个元素是1, (开始于1)
collection.Should().StartWith(1);
//元素开始 1,2
collection.Should().StartWith(new[] { 1, 2 });
//元素结束于 8
collection.Should().EndWith(8);
// 元素结束于5,8 有序的
collection.Should().EndWith(new[] { 5, 8 });
// 是不是参数的子集
collection.Should().BeSubsetOf(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, });
//collection.Should().ContainSingle(); // 只包含一个元素 会出错
// collection.Should().ContainSingle(x => x > 3); // 只有一个大于3, 会出错
collection.Should().Contain(8)
.And.HaveElementAt(2, 5) // 索引2的位置是5 (C#这种索引也是从0开始的)
.And.NotBeSubsetOf(new[] { 11, 56 }); //不是 11 56的子集
collection.Should().Contain(x => x > 3); // 含有大于3的元素 (这个是predicate 可以自己写各种需要判断)
var expected = new[] { 9 };
collection.Should().Contain(expected, "出错了{0}{1}", 5, 6); //出错了, Expected collection {1, 2, 5, 8} to contain 9 because 出错了56.
collection.Should().OnlyContain(x => x < 10); //只包含符合条件的 小于 10 的元素
collection.Should().ContainItemsAssignableTo<int>(); //所有的元素必须可以赋值给int类型
collection.Should().ContainInOrder(new[] { 1, 5, 8 }); // 包含 1 5 8 元素 有序的
collection.Should().NotContain(82); // 不包含82
collection.Should().NotContain(new[] { 82, 83 }); // // 不包含82 83 有序的
collection.Should().NotContainNulls(); // 不包含 null
collection.Should().NotContain(x => x > 10); // 不包含大于10
object boxedValue = 2;
collection.Should().ContainEquivalentOf(boxedValue); // 内部比较的时候是用Object.Equals 来比较的
collection = new[] { 1, 2, 9, 5, 8 };
// 在5之前的元素
collection.Should().HaveElementPreceding(5, 9);
//9 后面的元素 5
collection.Should().HaveElementSucceeding(9, 5);
//collection.Should().BeEmpty(); // 为空 有元素所以 断言失败
//collection.Should().BeNullOrEmpty();// 为空或者为null 断言失败
collection.Should().NotBeNullOrEmpty(); // 不为空或者不为Empty
var otherCollection = new[] { 1, 2, 5, 8, 1 };
var anotherCollection = new[] { 10, 20, 50, 80, 10 };
//跟参数的集合有交集
collection.Should().IntersectWith(otherCollection);
//跟参数的集合没有交集
collection.Should().NotIntersectWith(anotherCollection);
collection = new[] { 1, 2, 5, 8 };
collection.Should().BeInAscendingOrder(); //是否是升序排列。
//collection.Should().BeInDescendingOrder(); //是否倒序
// collection.Should().NotBeInAscendingOrder(); // 不是升序
collection.Should().NotBeInDescendingOrder(); //不是倒序
var stringCollection = new[] { "build succeded", "test failed" };
stringCollection.Should().ContainMatch("* failed"); //通配符判断 有没有 * failed 字符串
有时候集合里面的对象不是简单类型,我们可以用Lambda语法,把它取出来再断言。
using FluentAssertions;
using System.Linq;
using Xunit;
namespace MyFirstUnitTests
{
public class MyTestClass
{
[Fact]
public void Test_Example1()
{
var students1 = new[] {
new Student() { Name = "a1" },
new Student() { Name = "a2" }
};
var students2 = new[] {
new Student() { Name = "a1" },
new Student() { Name = "a2" },
};
// 把name取出 集合变成了 a1 a2, 断言元素都是唯一的
students1.Select(x => x.Name).Should().OnlyHaveUniqueItems();
// students1 的名字跟 students2 是不是相等, 内部的每一个元素都要相等
students1.Select(c => c.Name).Should().Equal(students2.Select(c => c.Name));
students1.Select(c => c.Name).Should().StartWith(students2.Select(c => c.Name));
students1.Select(c => c.Name).Should().EndWith(students2.Select(c => c.Name));
}
public class Student
{
public string Name { get; set; }
}
}
}
Fluent assertions也有一些方法支持直接判断里面的元素
using FluentAssertions;
using Xunit;
namespace MyFirstUnitTests
{
public class MyTestClass
{
[Fact]
public void Test_Example1()
{
var students1 = new Person[]
{
new Student() { Name = "a1" },
new Student() { Name = "a1" }
};
var s = new Student() { Name = "a1" };
// 是不是子元素都可以赋值给Student
students1.Should().AllBeAssignableTo<Student>();
// 是不是子元素都是 Student类型
students1.Should().AllBeOfType<Student>();
students1.Should().AllBeAssignableTo<Person>(); //断言成功。因为Student继承于Person
//students1.Should().AllBeOfType<Person>(); //断言失败,因为元素的实际类型是 Student
students1.Should().AllBeEquivalentTo(s);//是不是每个元素都跟s一样 (里面的值相等就行)
}
public class Student : Person
{
}
public class Person
{
public string Name { get; set; }
}
}
}
using FluentAssertions;
using Xunit;
namespace MyFirstUnitTests
{
public class MyTestClass
{
[Fact]
public void Test_Example1()
{
var students1 = new Student[]
{
new Student() { Name = "a1" },
new Student() { Name = "a2" }
};
//有两个元素就要写两个 action
students1.Should().SatisfyRespectively(
first =>
{
first.Name.Should().Be("a1");
},
second =>
{
second.Name.Should().Be("a1");
});
}
public class Student
{
public string Name { get; set; }
}
}
}
这边也可以换成下面的这种方式,看起来更简单了,更方便
using FluentAssertions;
using Xunit;
namespace MyFirstUnitTests
{
public class MyTestClass
{
[Fact]
public void Test_Example1()
{
var students1 = new Student[]
{
new Student() { Name = "a1" },
new Student() { Name = "a2" }
};
students1[0].Name.Should().Be("a1");
students1[1].Name.Should().Be("a2");
}
public class Student
{
public string Name { get; set; }
}
}
}