|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Globalization;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
using Xunit;
|
|
|
using xUnitStudy.Model;
|
|
|
|
|
|
namespace xUnitStudy.WebApi.Test
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// https://xunit.github.io/docs/comparisons
|
|
|
/// </summary>
|
|
|
[Trait("测试断言分组", "默认组")]
|
|
|
public class UseAssertTest : IDisposable
|
|
|
{
|
|
|
#region 准备
|
|
|
public UseAssertTest()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region Equal
|
|
|
[Fact]
|
|
|
public void Equal_String_Test()
|
|
|
{
|
|
|
Assert.Equal("ping", "ping");
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 断言 string 相等
|
|
|
/// 设置大小写、行尾符、空白符号 比较选项
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Equal_String_Ignore_Test()
|
|
|
{
|
|
|
//ignoreCase:忽略字符大小写差异.如果为true,比较时忽略字符大小写
|
|
|
Assert.Equal("ABcdEF", "abcdef", ignoreCase: true);
|
|
|
|
|
|
//ignoreLineEndingDifferences:忽略行尾结束符差异。设置为true,则将\rn、\r和\n视为等效。
|
|
|
Assert.Equal("One line\r\n", "one line\n", ignoreCase: true, ignoreLineEndingDifferences: true);
|
|
|
|
|
|
//ignoreWhiteSpaceDifferences:忽略"空白"(空格、Tab)差异。设置为true,则将空格和制表符(以任何非零量)视为等效。
|
|
|
Assert.Equal("One line\r", "one line\n", ignoreCase: true, ignoreLineEndingDifferences: true, ignoreWhiteSpaceDifferences: true);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Equal_Double_Test()
|
|
|
{
|
|
|
//注意:先舍入,然后再比较
|
|
|
//舍入规则:四舍五入
|
|
|
//精度范围[0,15]位小数
|
|
|
|
|
|
Assert.Equal(1.14d, 1.11d, precision: 1);
|
|
|
Assert.Equal(1.15d, 1.19d, precision: 1);
|
|
|
|
|
|
Assert //1.14d 约等于1.1 而1.15d 约等于1.2 所以不相等
|
|
|
.NotEqual(1.14d, 1.15d, precision: 1);
|
|
|
|
|
|
//四舍五入到2位小数精度,相等
|
|
|
Assert.Equal(2.123d, 2.124d, 2);
|
|
|
|
|
|
//四舍五入到3位小数精度,相等
|
|
|
Assert.Equal(3.1234d, 3.1231d, 3);
|
|
|
|
|
|
//四舍五入到4位小数精度,不等
|
|
|
Assert.NotEqual(3.12345d, 3.12349d, 4);
|
|
|
|
|
|
//四舍五入到整数,相等
|
|
|
Assert.Equal(15d, 15.111d, precision: 0);
|
|
|
|
|
|
//没有小数位,四舍五入到整数
|
|
|
Assert.Equal(15d, 15d, precision: 0);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Equal_Decimal_Test()
|
|
|
{
|
|
|
//注意:先舍入,然后再比较
|
|
|
//舍入规则:四舍五入
|
|
|
//精度范围[0,15]位小数
|
|
|
|
|
|
Assert.Equal(1.14M, 1.11M, precision: 1);
|
|
|
Assert.Equal(1.15M, 1.19M, precision: 1);
|
|
|
|
|
|
Assert //1.14M 约等于1.1 而1.15M 约等于1.2 所以不相等
|
|
|
.NotEqual(1.14M, 1.15M, precision: 1);
|
|
|
|
|
|
//四舍五入到2位小数精度,相等
|
|
|
Assert.Equal(2.123M, 2.124M, 2);
|
|
|
|
|
|
//四舍五入到3位小数精度,相等
|
|
|
Assert.Equal(3.1234M, 3.1231M, 3);
|
|
|
|
|
|
//四舍五入到4位小数精度,不等
|
|
|
Assert.NotEqual(3.12345M, 3.12349M, 4);
|
|
|
|
|
|
//四舍五入到整数,相等
|
|
|
Assert.Equal(15M, 15.111M, precision: 0);
|
|
|
|
|
|
//没有小数位,四舍五入到整数
|
|
|
Assert.Equal(15M, 15M, precision: 0);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Equal_Datetime_Test()
|
|
|
{
|
|
|
Assert.Equal(DateTime.Now, DateTime.Now.AddSeconds(1), TimeSpan.FromSeconds(2));
|
|
|
Assert.Equal(DateTime.Now, DateTime.Now.AddMinutes(1), TimeSpan.FromMinutes(2));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// Equal 泛型版本
|
|
|
/// 泛型版基本上都有简化写法
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Equal_Generic_T_Test()
|
|
|
{
|
|
|
//形如:Assert.Equal<T>(Expected T, Actual T);
|
|
|
//常见类型都可以简化,或是有更好的非泛型版,此时,一般用非泛型版
|
|
|
|
|
|
Assert.Equal<string>("ping", "ping");
|
|
|
Assert //基本使用非泛型版本
|
|
|
.Equal("ping", "ping");
|
|
|
|
|
|
Assert.Equal<int>(3, 3);
|
|
|
Assert //简化为
|
|
|
.Equal(3, 3);
|
|
|
|
|
|
Assert.Equal<long>(3L, 3L);
|
|
|
Assert //简化为
|
|
|
.Equal(3L, 3L);
|
|
|
|
|
|
Assert.Equal<double>(5.5d, 5.5d);
|
|
|
Assert //简化为
|
|
|
.Equal(5.5d, 5.5d);
|
|
|
|
|
|
Assert.Equal<decimal>(5.5M, 5.5M);
|
|
|
Assert //简化为
|
|
|
.Equal(5.5M, 5.5M);
|
|
|
|
|
|
Assert.Equal<DateTime>(DateTime.Now.Date, DateTime.Now.Date);
|
|
|
Assert //简化为
|
|
|
.Equal(DateTime.Now.Date, DateTime.Now.Date);
|
|
|
|
|
|
//类或其它自定义结构比较,可以使用
|
|
|
|
|
|
var obj = new object();
|
|
|
Assert.Equal<object>(obj, obj);
|
|
|
Assert //简化为
|
|
|
.Equal(obj, obj);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// Equal 实现了IEqualityComparer接口的泛型版本
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Equal_Generic_IEqualityComparer_Test()
|
|
|
{
|
|
|
//形如:Assert.Equal<T>(Expected T, Actual T,IEqualityComparer comparer);
|
|
|
//实现 IEqualityComparer 接口
|
|
|
|
|
|
var expected = new AssertEqualDemo() { Id = 1, Name = "zhansan" };
|
|
|
var actual = new AssertEqualDemo() { Id = 1, Name = "lisi" };
|
|
|
|
|
|
//实现 IEqualityComparer 接口的,可以是被比较对象自己实现接口,也可以是单独的类。
|
|
|
var comparer = new AssertEqualDemo();
|
|
|
|
|
|
Assert.Equal<AssertEqualDemo>(expected, actual, comparer);
|
|
|
Assert.//可以简写为
|
|
|
Equal(expected, actual, comparer);
|
|
|
|
|
|
//id不一样,则不相等
|
|
|
expected.Id = 3;
|
|
|
Assert.NotEqual(expected, actual, comparer);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 实现IEnumerable接口对象的 Equal比较
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Equal_Generic_IEnumerable_Test()
|
|
|
{
|
|
|
//对实现IEnumerable接口的对象进行 Equal比较
|
|
|
//形如:Equal<T>(IEnumerable<T> expected, IEnumerable<T> actual);
|
|
|
|
|
|
List<string> expected = new List<string>() { "first", "second" };
|
|
|
List<string> actual = new List<string>() { "first", "second" };
|
|
|
|
|
|
Assert.Equal<List<string>>(expected, actual);
|
|
|
Assert.//简写为
|
|
|
Equal(expected, actual);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 实现IEnumerable接口对象的 Equal 比较
|
|
|
/// 传入实现IEqualityComparer接口的比较器
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Equal_Generic_IEnumerable_IEqualityComparer_Test()
|
|
|
{
|
|
|
//对实现IEnumerable接口的对象进行 Equal比较
|
|
|
//形如:Equal<T>(IEnumerable<T> expected, IEnumerable<T> actual,IEqualityComparer comparer)
|
|
|
//传入实现了 IEqualityComparer 接口的比较参数
|
|
|
|
|
|
var expected = new List<AssertEqualDemo>()
|
|
|
{
|
|
|
new AssertEqualDemo() { Id = 1, Name = "zhansan" },
|
|
|
new AssertEqualDemo() { Id = 2, Name = "lis" },
|
|
|
};
|
|
|
var actual = new List<AssertEqualDemo>()
|
|
|
{
|
|
|
new AssertEqualDemo() { Id = 1, Name = "wangwu" },
|
|
|
new AssertEqualDemo() { Id = 2, Name = "zhaoliu" },
|
|
|
};
|
|
|
|
|
|
//实现 IEqualityComparer 接口的,可以是被比较对象自己实现接口,也可以是单独的类。
|
|
|
var comparer = new AssertEqualDemo();
|
|
|
|
|
|
Assert.Equal<AssertEqualDemo>(expected, actual, comparer);
|
|
|
Assert.//可以简写为
|
|
|
Equal(expected, actual, comparer);
|
|
|
|
|
|
//id不一样,则不相等
|
|
|
expected[0].Id = 100;
|
|
|
Assert.NotEqual(expected, actual, comparer);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region NotEqual
|
|
|
[Fact]
|
|
|
public void NotEqual_String_Test()
|
|
|
{
|
|
|
Assert.NotEqual("ping", "ack");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotEqual_Double_Test()
|
|
|
{
|
|
|
//注意:先舍入,然后再比较
|
|
|
//舍入规则:四舍五入
|
|
|
//精度范围[0,15]位小数
|
|
|
|
|
|
Assert //1.14d 约等于1.1 而1.15d 约等于1.2 所以不相等
|
|
|
.NotEqual(1.14d, 1.15d, precision: 1);
|
|
|
|
|
|
//舍入到2位小数精度,相等
|
|
|
Assert.NotEqual(2.124d, 2.126d, 2);
|
|
|
|
|
|
//舍入到3位小数精度,相等
|
|
|
Assert.NotEqual(3.1234d, 3.1239d, 3);
|
|
|
|
|
|
//舍入到4位小数精度,不等
|
|
|
Assert.NotEqual(3.12346d, 3.12341d, 4);
|
|
|
|
|
|
//舍入到整数,相等
|
|
|
Assert.NotEqual(16d, 15.111d, precision: 0);
|
|
|
|
|
|
//没有小数位,舍入到整数
|
|
|
Assert.NotEqual(16d, 160d, precision: 0);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotEqual_Decimal_Test()
|
|
|
{
|
|
|
//注意:先舍入,然后再比较
|
|
|
//舍入规则:四舍五入
|
|
|
//精度范围[0,15]位小数
|
|
|
|
|
|
Assert //1.14M 约等于1.1 而1.15M 约等于1.2 所以不相等
|
|
|
.NotEqual(1.14M, 1.15M, precision: 1);
|
|
|
|
|
|
//四舍五入到2位小数精度,不等
|
|
|
Assert.NotEqual(2.123M, 2.129M, 2);
|
|
|
|
|
|
//四舍五入到3位小数精度,不等
|
|
|
Assert.NotEqual(3.1234M, 3.1236M, 3);
|
|
|
|
|
|
//四舍五入到4位小数精度,不等
|
|
|
Assert.NotEqual(3.12345M, 3.12349M, 4);
|
|
|
|
|
|
//四舍五入到整数,不等
|
|
|
Assert.NotEqual(15M, 15.501M, precision: 0);
|
|
|
|
|
|
//没有小数位,四舍五入到整数
|
|
|
Assert.NotEqual(29M, 15M, precision: 0);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotEqual_Generic_T_Test()
|
|
|
{
|
|
|
//形如:Assert.NotEqual<T>(Expected T, Actual T);
|
|
|
|
|
|
Assert.NotEqual<string>("ping", "ack");
|
|
|
Assert //基本使用非泛型版本
|
|
|
.NotEqual("ping", "ack");
|
|
|
|
|
|
Assert.NotEqual<int>(3, 4);
|
|
|
Assert //简化为
|
|
|
.NotEqual(3, 4);
|
|
|
|
|
|
Assert.NotEqual<long>(3L, 4L);
|
|
|
Assert //简化为
|
|
|
.NotEqual(3L, 4L);
|
|
|
|
|
|
Assert.NotEqual<double>(5.5d, 6.5d);
|
|
|
Assert //简化为
|
|
|
.NotEqual(5.5d, 6.5d);
|
|
|
|
|
|
Assert.NotEqual<decimal>(5.5M, 5.6M);
|
|
|
Assert //简化为
|
|
|
.NotEqual(5.5M, 6.5M);
|
|
|
|
|
|
Assert.NotEqual<DateTime>(DateTime.Now.Date, DateTime.Now.Date.AddDays(1));
|
|
|
Assert //简化为
|
|
|
.NotEqual(DateTime.Now.Date, DateTime.Now.Date.AddDays(1));
|
|
|
|
|
|
//类或其它自定义结构比较,可以使用
|
|
|
|
|
|
var obj = new object();
|
|
|
var obj2 = new object();
|
|
|
Assert.NotEqual<object>(obj, obj2);
|
|
|
Assert //简化为
|
|
|
.NotEqual(obj, obj2);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotEqual_Generic_IEqualityComparer_Test()
|
|
|
{
|
|
|
//形如:Assert.NotEqual<T>(Expected T, Actual T,IEqualityComparer comparer);
|
|
|
//实现 IEqualityComparer 接口
|
|
|
|
|
|
var expected = new AssertEqualDemo() { Id = 1, Name = "zhansan" };
|
|
|
var actual = new AssertEqualDemo() { Id = 1, Name = "lishi" };
|
|
|
|
|
|
//实现 IEqualityComparer 接口的,可以是被比较对象自己实现接口,也可以是单独的类。
|
|
|
var comparer = new AssertEqualDemo();
|
|
|
|
|
|
Assert.Equal<AssertEqualDemo>(expected, actual, comparer);
|
|
|
Assert.//可以简写为
|
|
|
Equal(expected, actual, comparer);
|
|
|
|
|
|
//id不一样,则不相等
|
|
|
expected.Id = 3;
|
|
|
Assert.NotEqual(expected, actual, comparer);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotEqual_Generic_IEnumerable_Test()
|
|
|
{
|
|
|
//对实现IEnumerable接口的对象进行 Equal比较
|
|
|
//形如:NotEqual<T>(IEnumerable<T> expected, IEnumerable<T> actual)
|
|
|
|
|
|
List<string> expected = new List<string>() { "first", "second", "third" };
|
|
|
List<string> actual = new List<string>() { "first", "second" };
|
|
|
|
|
|
Assert.NotEqual<List<string>>(expected, actual);
|
|
|
Assert.//简写为
|
|
|
NotEqual(expected, actual);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotEqual_Generic_IEnumerable_IEqualityComparer_Test()
|
|
|
{
|
|
|
//对实现IEnumerable接口的对象进行 Equal比较
|
|
|
//形如:NotEqual<T>(IEnumerable<T> expected, IEnumerable<T> actual,IEqualityComparer comparer)
|
|
|
//传入实现了 IEqualityComparer 接口的比较参数
|
|
|
|
|
|
var expected = new List<AssertEqualDemo>()
|
|
|
{
|
|
|
new AssertEqualDemo() { Id = 1, Name = "zhansan" },
|
|
|
new AssertEqualDemo() { Id = 2, Name = "lis" },
|
|
|
};
|
|
|
var actual = new List<AssertEqualDemo>()
|
|
|
{
|
|
|
new AssertEqualDemo() { Id = 1, Name = "wangwu" },
|
|
|
new AssertEqualDemo() { Id = 2, Name = "zhaoliu" },
|
|
|
};
|
|
|
|
|
|
//实现 IEqualityComparer 接口的,可以是被比较对象自己实现接口,也可以是单独的类。
|
|
|
var comparer = new AssertEqualDemo();
|
|
|
|
|
|
Assert.Equal<AssertEqualDemo>(expected, actual, comparer);
|
|
|
Assert.//可以简写为
|
|
|
Equal(expected, actual, comparer);
|
|
|
|
|
|
//id不一样,则不相等
|
|
|
expected[0].Id = 100;
|
|
|
Assert.NotEqual(expected, actual, comparer);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region StrictEqual
|
|
|
[Fact]
|
|
|
public void StrictEqual_Test()
|
|
|
{
|
|
|
//使用类型的默认比较器验证两个对象是否严格相等,用法类似Equal<T>
|
|
|
//不支持自定义IEqualityComparer<T>
|
|
|
Assert.StrictEqual<decimal>(1L, 1m);
|
|
|
|
|
|
|
|
|
Person person1 = new Person() { Id = 2 };
|
|
|
Person person2 = new Person() { Id = 2 };
|
|
|
|
|
|
Person person3 = new Person() { Id = 1 };
|
|
|
IPerson person4 = person3;
|
|
|
|
|
|
Assert.StrictEqual(person3, person4);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotStrictEqual_Test()
|
|
|
{
|
|
|
//使用类型的默认比较器验证两个对象是否严格相等,用法类似NotEqual<T>
|
|
|
//不支持自定义IEqualityComparer<T>
|
|
|
Assert.NotStrictEqual<decimal>(2.55M, 3.55M);
|
|
|
|
|
|
|
|
|
Person person1 = new Person() { Id = 2 };
|
|
|
Person person2 = new Person() { Id = 2 };
|
|
|
|
|
|
Person person3 = new Person() { Id = 1 };
|
|
|
IPerson person4 = person1;
|
|
|
|
|
|
Assert.NotStrictEqual(person1, person2);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region Same
|
|
|
[Fact]
|
|
|
public void Same_String_Test()
|
|
|
{
|
|
|
//验证两个引用类型的对象,是同一个实例
|
|
|
//注意:必须是引用类型,不能是值类型
|
|
|
|
|
|
//特别注明:sting类型,虽然是引用类型,但是比较特殊。采取复制策略,相同值可以(不严谨的说法)认为引用相同
|
|
|
string expected = "hell,world!";
|
|
|
string actual = "hell,world!";
|
|
|
Assert.Same(expected, actual);
|
|
|
|
|
|
string expected2 = "hell,world!";
|
|
|
string actual2 = expected2;
|
|
|
Assert.Same(expected2, actual2);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Same_Object_Test()
|
|
|
{
|
|
|
object obj1 = new object();
|
|
|
object obj2 = new object();
|
|
|
object obj3 = obj1;
|
|
|
object obj4 = obj2;
|
|
|
|
|
|
Assert.Same(obj1, obj3);
|
|
|
Assert.Same(obj2, obj4);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Same_Class_Test()
|
|
|
{
|
|
|
object obj1 = new AssertEqualDemo() { Id = 1, Name = "zhangsan" };
|
|
|
object obj2 = new AssertEqualDemo() { Id = 1, Name = "zhangsan" };
|
|
|
object obj3 = obj1;
|
|
|
object obj4 = obj2;
|
|
|
|
|
|
Assert.Same(obj1, obj3);
|
|
|
Assert.Same(obj2, obj4);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region NotSame
|
|
|
[Fact]
|
|
|
public void NotSame_String_Test()
|
|
|
{
|
|
|
//验证两个引用类型的对象,是同一个实例
|
|
|
//注意:必须是引用类型,不能是值类型
|
|
|
|
|
|
//特别注明:sting类型,虽然是引用类型,但是比较特殊。采取复制策略,相同值可以(不严谨的说法)认为引用相同
|
|
|
string expected = "hell,world!";
|
|
|
string actual = "I am chinese!";
|
|
|
Assert.NotSame(expected, actual);
|
|
|
|
|
|
Assert.NotSame("abc", "xyz");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotSame_Object_Test()
|
|
|
{
|
|
|
object obj1 = new object();
|
|
|
object obj2 = new object();
|
|
|
Object obj3 = obj2;
|
|
|
|
|
|
Assert.NotSame(obj1, obj2);
|
|
|
Assert.NotSame(obj1, obj3);
|
|
|
Assert.NotSame(new object(), new object());
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotSame_Class_Test()
|
|
|
{
|
|
|
object obj1 = new AssertEqualDemo() { Id = 1, Name = "zhangsan" };
|
|
|
object obj2 = new AssertEqualDemo() { Id = 1, Name = "zhangsan" };
|
|
|
object obj3 = obj1;
|
|
|
object obj4 = obj2;
|
|
|
|
|
|
Assert.NotSame(obj1, obj2);
|
|
|
Assert.NotSame(obj3, obj4);
|
|
|
Assert.NotSame(obj1, obj4);
|
|
|
Assert.NotSame(obj2, obj3);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region True
|
|
|
[Fact]
|
|
|
public void True_Condition_Test()
|
|
|
{
|
|
|
Assert.True(true);
|
|
|
Assert.True("ping" == "ping");
|
|
|
Assert.True(2 == 1 + 1);
|
|
|
Assert.True("ping" == "ping" && 2 == 1 + 1);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void True_Nullable_Test()
|
|
|
{
|
|
|
bool? expected = null;
|
|
|
Assert.True(!expected.HasValue);
|
|
|
|
|
|
int? expected2 = null;
|
|
|
Assert.True(expected2 == null);
|
|
|
expected2 = 2;
|
|
|
Assert.True(2 == expected2.Value);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void True_Message_Test()
|
|
|
{
|
|
|
Assert.True(true, "userMessage");
|
|
|
Assert.True("ping" == "ping", "userMessage");
|
|
|
Assert.True(2 == 1 + 1, "userMessage");
|
|
|
|
|
|
int? nullableInt = null;
|
|
|
Assert.True(null == nullableInt, "userMessage");
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region False
|
|
|
[Fact]
|
|
|
public void False_Condition_Test()
|
|
|
{
|
|
|
Assert.False(false);
|
|
|
Assert.False("ping" == "ack");
|
|
|
Assert.False(3 == 1 + 1);
|
|
|
Assert.False("ping" == "ping" && 3 == 1 + 1);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void False_Nullable_Test()
|
|
|
{
|
|
|
bool? expected = null;
|
|
|
Assert.False(expected.HasValue);
|
|
|
|
|
|
int? expected2 = 3;
|
|
|
Assert.False(expected2 == null);
|
|
|
Assert.False(4 == expected2.Value);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void False_Message_Test()
|
|
|
{
|
|
|
Assert.False(false, "userMessage");
|
|
|
Assert.False("ping" == "ack", "userMessage");
|
|
|
Assert.False(2 == 1 + 3, "userMessage");
|
|
|
|
|
|
int? nullableInt = 3;
|
|
|
Assert.False(null == nullableInt, "userMessage");
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region True|False 可替代断言
|
|
|
/// <summary>
|
|
|
/// 直接设置验证通过
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Pass_Test()
|
|
|
{
|
|
|
Assert.True(true, "用True断言替代");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Fail_Test()
|
|
|
{
|
|
|
//Assert.True(false, "用True断言替代");
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 大于
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void GreaterThan_Test()
|
|
|
{
|
|
|
Assert //大于比较,用True(x > y) 替代
|
|
|
.True(2 > 1);
|
|
|
|
|
|
int max = 5;
|
|
|
int min = 2;
|
|
|
|
|
|
Assert.True(max > min);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 小于
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void LessThan_Test()
|
|
|
{
|
|
|
Assert //小于比较,用True(x < y) 替代
|
|
|
.True(2 < 3);
|
|
|
|
|
|
int max = 5;
|
|
|
int min = 2;
|
|
|
|
|
|
Assert.True(min < max);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NaN_Test()
|
|
|
{
|
|
|
//NaN=Not a Number,是否不为数字
|
|
|
|
|
|
//说明:在浮点数计算中,0除以0将得到NaN,正数除以0将得到PositiveInfinity,负数除以0将得到NegativeInfinity。
|
|
|
//浮点数运算从不引发异常
|
|
|
|
|
|
Assert.True(double.IsNaN(0 / 0d));
|
|
|
|
|
|
Assert.True(double.IsPositiveInfinity(1 / 0d));
|
|
|
|
|
|
Assert.True(double.IsNegativeInfinity(-1 / 0d));
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region Null|Empty
|
|
|
[Fact]
|
|
|
public void Empty_Test()
|
|
|
{
|
|
|
List<string> expected = new List<string>();
|
|
|
|
|
|
Assert //针对于集合,为Empty,即是集合中元素的个数为0。但集合为空引用null值时将引发异常
|
|
|
.Empty(expected);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotEmpty_Test()
|
|
|
{
|
|
|
List<string> expected = new List<string>() { "first", "second" };
|
|
|
|
|
|
Assert //针对于集合,不为Empty,即是集合中元素的个数大于0。集合为空引用null值时将引发异常
|
|
|
.NotEmpty(expected);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Null_Test()
|
|
|
{
|
|
|
Assert //null值,空引用
|
|
|
.Null(null);
|
|
|
|
|
|
string exp = null;
|
|
|
Assert.Null(exp);
|
|
|
|
|
|
List<string> list = null;
|
|
|
Assert.Null(list);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotNull_Test()
|
|
|
{
|
|
|
Assert //null值,空引用
|
|
|
.NotNull(new object());
|
|
|
|
|
|
Assert.NotNull("");
|
|
|
Assert.NotNull(string.Empty);
|
|
|
|
|
|
Assert.NotNull(new List<string>());
|
|
|
|
|
|
Assert.NotNull(new List<string>() { "first", "second" });
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region Type|Assignable
|
|
|
[Fact]
|
|
|
public void IsType_Test()
|
|
|
{
|
|
|
//此形式,只在泛型不能使用时,才使用;应优先使用泛型版。
|
|
|
Assert.IsType(typeof(string), "aaaa");
|
|
|
|
|
|
//泛型版
|
|
|
Assert.IsType<string>("hell,world!");
|
|
|
Assert.IsType<int>(2);
|
|
|
Assert.IsType<long>(2L);
|
|
|
Assert.IsType<double>(2d);
|
|
|
Assert.IsType<decimal>(2M);
|
|
|
Assert.IsType<DateTime>(DateTime.Now);
|
|
|
Assert.IsType<AssertEqualDemo>(new AssertEqualDemo());
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void IsNotType_Test()
|
|
|
{
|
|
|
//此形式,只在泛型不能使用时,才使用;应优先使用泛型版。
|
|
|
Assert.IsNotType(typeof(string), 22);
|
|
|
|
|
|
//泛型版
|
|
|
Assert.IsNotType<string>(2);
|
|
|
Assert.IsNotType<int>("hello");
|
|
|
Assert.IsNotType<long>("521");
|
|
|
Assert.IsNotType<double>(new object());
|
|
|
Assert.IsNotType<decimal>("55555");
|
|
|
Assert.IsNotType<DateTime>("2018-08-03");
|
|
|
Assert.IsNotType<AssertEqualDemo>(new object());
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void IsAssignableFrom_Test()
|
|
|
{
|
|
|
//可以从指定的类型派生
|
|
|
Assert.IsAssignableFrom<object>(22);
|
|
|
|
|
|
|
|
|
Person person = new Person() { Id = 1, FirstName = "first", LastName = "last" };
|
|
|
Assert. //接口派生
|
|
|
IsAssignableFrom<IPerson>(person);
|
|
|
|
|
|
Teacher teacher = new Teacher() { Id = 1, FirstName = "first", LastName = "last", Grade = 2 };
|
|
|
Assert. //类继承
|
|
|
IsAssignableFrom<Person>(teacher);
|
|
|
|
|
|
Assert //接口派生
|
|
|
.IsAssignableFrom<IPerson>(teacher);
|
|
|
|
|
|
|
|
|
Assert //万源归宗
|
|
|
.IsAssignableFrom<object>(teacher);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 断言非派生、继承关系
|
|
|
/// Assert.False(obj is Type)替代
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void IsNotAssignableFrom_Test()
|
|
|
{
|
|
|
// Assert.False(obj is Type) 替代
|
|
|
|
|
|
//可以从指定的类型派生
|
|
|
Assert.False(88 is String);
|
|
|
Assert.False(new object() is int);
|
|
|
|
|
|
Person person = new Person() { Id = 1, FirstName = "first", LastName = "last" };
|
|
|
Teacher teacher = new Teacher() { Id = 2, FirstName = "first", LastName = "last", Grade = 2 };
|
|
|
IPerson person2 = new Person() { Id = 3, FirstName = "first", LastName = "last" };
|
|
|
|
|
|
Assert.False(person is Teacher);
|
|
|
Assert.False(person2 is Teacher);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region Contains For String
|
|
|
[Fact]
|
|
|
public void Contains_String_Test()
|
|
|
{
|
|
|
Assert.Contains("hello", "hello,world.");
|
|
|
Assert.Contains("llo", "hello,world.");
|
|
|
Assert.Contains("world", "hello,world.");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_String_Comparison_Ordinal_Test()
|
|
|
{
|
|
|
//StringComparison.Ordinal 二进制比较:最快,最严格
|
|
|
//进行非语言(non-linguistic)上的比较,对两个字符串进行byte级别的比较,比较结果严格而准确,性能非常好。
|
|
|
Assert.Contains("hello", "hello,world", StringComparison.Ordinal);
|
|
|
Assert.Contains("llo", "hello,world", StringComparison.Ordinal);
|
|
|
Assert.Contains("orld", "hello,world", StringComparison.Ordinal);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_String_Comparison_OrdinalIgnoreCase_Test()
|
|
|
{
|
|
|
//StringComparison.OrdinalIgnoreCase与StringComparison.Ordinal相同,只是不区分大小写
|
|
|
Assert.Contains("hello", "Hello,World", StringComparison.OrdinalIgnoreCase);
|
|
|
Assert.Contains("llo", "Hello,World", StringComparison.OrdinalIgnoreCase);
|
|
|
Assert.Contains("orld", "Hello,World", StringComparison.OrdinalIgnoreCase);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_String_Comparison_CurrentCulture_Test()
|
|
|
{
|
|
|
//StringComparison.CurrentCulture 默认的比较方式:使用区域敏感排序规则和当前区域比较字符串
|
|
|
//在当前的区域信息下进行比较,这是String.Compare在没有指定StringComparison的时候默认的比较方式
|
|
|
|
|
|
Assert.Contains("", "", StringComparison.CurrentCulture);
|
|
|
Assert.Contains("orl", "hello,world", StringComparison.CurrentCulture);
|
|
|
|
|
|
//设置特定区域
|
|
|
string s1 = "encyclopædia";
|
|
|
string s2 = "encyclopaedia";
|
|
|
|
|
|
//当前的区域信息是美国:s1与s2是相等的。
|
|
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
|
|
|
Assert.Contains(s1, s2, StringComparison.CurrentCulture);
|
|
|
|
|
|
//当前的区域信息是se-SE,s1与s2是相等的
|
|
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("se-SE");
|
|
|
Assert.DoesNotContain(s1, s2, StringComparison.CurrentCulture);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_String_Comparison_CurrentCultureIgnoreCase_Test()
|
|
|
{
|
|
|
//用法同:StringComparison.CurrentCulture,只是不区分大小写
|
|
|
|
|
|
Assert.Contains("A", "aBB", StringComparison.CurrentCultureIgnoreCase);
|
|
|
Assert.Contains("worl", "Hello,World", StringComparison.CurrentCultureIgnoreCase);
|
|
|
|
|
|
//设置特定区域
|
|
|
string s1 = "Encyclopædia";
|
|
|
string s2 = "encyclopaediA";
|
|
|
|
|
|
//当前的区域信息是美国:s1与s2是相等的。
|
|
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
|
|
|
Assert.Contains(s1, s2, StringComparison.CurrentCultureIgnoreCase);
|
|
|
|
|
|
//当前的区域信息是se-SE,s1与s2是相等的
|
|
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("se-SE");
|
|
|
Assert.DoesNotContain(s1, s2, StringComparison.CurrentCultureIgnoreCase);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_String_Comparison_InvariantCulture_Test()
|
|
|
{
|
|
|
//StringComparison.InvariantCulture:使用区域敏感排序规则和固定区域比较字符串
|
|
|
//在任何系统中(不同的culture)比较都将得到相同的结果,他是使用CultureInfo.InvariantCulture的静态成员CompareInfo来进行比较操作的.
|
|
|
//StringComparison.InvariantCultureIgnoreCase与StringComparison.InvariantCulture,只是忽略大小写
|
|
|
|
|
|
Assert.Contains("ping", "ping", StringComparison.InvariantCulture);
|
|
|
Assert.Contains("p", "ping", StringComparison.InvariantCulture);
|
|
|
Assert.Contains("in", "ping", StringComparison.InvariantCulture);
|
|
|
Assert.Contains("ing", "ping", StringComparison.InvariantCulture);
|
|
|
|
|
|
//区域无关性
|
|
|
string s1 = "encyclopædia";
|
|
|
string s2 = "encyclopaedia";
|
|
|
|
|
|
Assert.Contains(s1, s2, StringComparison.InvariantCulture);
|
|
|
|
|
|
//设置区为美国:无效
|
|
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
|
|
|
Assert.Contains(s1, s2, StringComparison.InvariantCulture);
|
|
|
|
|
|
//设置区为se-SE:无效
|
|
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("se-SE");
|
|
|
Assert.Contains(s1, s2, StringComparison.InvariantCulture);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_String_Comparison_InvariantCultureIgnoreCase_Test()
|
|
|
{
|
|
|
//StringComparison.InvariantCultureIgnoreCase与StringComparison.InvariantCulture,只是忽略大小写
|
|
|
|
|
|
Assert.Contains("ping", "PinG", StringComparison.InvariantCultureIgnoreCase);
|
|
|
Assert.Contains("p", "PinG", StringComparison.InvariantCultureIgnoreCase);
|
|
|
Assert.Contains("in", "PinG", StringComparison.InvariantCultureIgnoreCase);
|
|
|
Assert.Contains("ing", "PinG", StringComparison.InvariantCultureIgnoreCase);
|
|
|
|
|
|
//区域无关性
|
|
|
string s1 = "Encyclopædia";
|
|
|
string s2 = "encyclopaediA";
|
|
|
|
|
|
Assert.Contains(s1, s2, StringComparison.InvariantCultureIgnoreCase);
|
|
|
|
|
|
//设置区为美国:无效
|
|
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
|
|
|
Assert.Contains(s1, s2, StringComparison.InvariantCultureIgnoreCase);
|
|
|
|
|
|
//设置区为se-SE:无效
|
|
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("se-SE");
|
|
|
Assert.Contains(s1, s2, StringComparison.InvariantCultureIgnoreCase);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region Contains Collection
|
|
|
[Fact]
|
|
|
public void Contains_Generic_In_IEnumerable_Test()
|
|
|
{
|
|
|
//字符数组
|
|
|
var stringArray = new List<string>() { "first", "second", "third", "four" };
|
|
|
Assert.Contains<string>("first", stringArray);
|
|
|
Assert //可以简化写法
|
|
|
.Contains("second", stringArray);
|
|
|
|
|
|
//int 数组
|
|
|
var intArray = new List<int>() { 1, 2, 3, 4, 5 };
|
|
|
Assert.Contains<int>(2, intArray);
|
|
|
Assert //可以简化写法
|
|
|
.Contains(3, intArray);
|
|
|
|
|
|
//类组
|
|
|
|
|
|
//内部各项都相等,但实例(引用)不同,则不包含
|
|
|
var classArray = new List<Person>()
|
|
|
{
|
|
|
new Person(){ Id=1, FirstName="first1", LastName="last1"},
|
|
|
new Person(){ Id=2, FirstName="first2", LastName="last2"},
|
|
|
new Person(){ Id=3, FirstName="first3", LastName="last3"},
|
|
|
};
|
|
|
|
|
|
Person person1 = new Person() { Id = 1, FirstName = "first1", LastName = "last1" };
|
|
|
Person person2 = new Person() { Id = 2, FirstName = "first2", LastName = "last2" };
|
|
|
Person person3 = new Person() { Id = 3, FirstName = "first3", LastName = "last3" };
|
|
|
|
|
|
Assert.DoesNotContain<Person>(person1, classArray);
|
|
|
Assert //简化写法
|
|
|
.DoesNotContain(person2, classArray);
|
|
|
Assert //简化写法
|
|
|
.DoesNotContain(person3, classArray);
|
|
|
|
|
|
//相同的引用才包含
|
|
|
classArray.Add(person1);
|
|
|
classArray.Add(person2);
|
|
|
classArray.Add(person3);
|
|
|
|
|
|
Assert.Contains(person1, classArray);
|
|
|
Assert.Contains(person2, classArray);
|
|
|
Assert.Contains(person3, classArray);
|
|
|
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_Generic_In_IEnumerable_IEqualityComparer_Test()
|
|
|
{
|
|
|
//以 IEqualityComparer 比较器为断言依据
|
|
|
|
|
|
Person person1 = new Person() { Id = 1, FirstName = "first1", LastName = "last1" };
|
|
|
Person person2 = new Person() { Id = 2, FirstName = "first2", LastName = "last2" };
|
|
|
Person person3 = new Person() { Id = 3, FirstName = "first3", LastName = "last3" };
|
|
|
|
|
|
var classArray = new List<Person>()
|
|
|
{
|
|
|
new Person() { Id = 1, FirstName = "ab", LastName = "cd" },
|
|
|
new Person() { Id = 2, FirstName = "ef", LastName = "g" },
|
|
|
new Person() { Id = 3, FirstName = "s", LastName = "b" },
|
|
|
};
|
|
|
|
|
|
//自定义比较器
|
|
|
IEqualityComparer<Person> equalityComparer = new Person();
|
|
|
|
|
|
Assert.Contains(person1, classArray, equalityComparer);
|
|
|
Assert.Contains(person2, classArray, equalityComparer);
|
|
|
Assert.Contains(person3, classArray, equalityComparer);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_Generic_IEnumerable_Filter_Test()
|
|
|
{
|
|
|
Person person1 = new Person() { Id = 1, FirstName = "first1", LastName = "last1" };
|
|
|
Person person2 = new Person() { Id = 2, FirstName = "first2", LastName = "last2" };
|
|
|
Person person3 = new Person() { Id = 3, FirstName = "first3", LastName = "last3" };
|
|
|
|
|
|
var classArray = new List<Person>()
|
|
|
{
|
|
|
person1,
|
|
|
person2,
|
|
|
person3,
|
|
|
};
|
|
|
|
|
|
//Predicate<T> 委托(入参T,返回 bool),作为筛选条件
|
|
|
Assert.Contains<Person>(classArray, person => person.Id == 1);
|
|
|
Assert //简写为
|
|
|
.Contains<Person>(classArray, person => person.FirstName == "first1");
|
|
|
Assert //简写为
|
|
|
.Contains<Person>(classArray, person => person.Id == 3 && person.LastName == "last3");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_Generic_In_IDictionary_Test()
|
|
|
{
|
|
|
//字符串
|
|
|
KeyValuePair<string, string> sring_kv1 = new KeyValuePair<string, string>("key1", "first");
|
|
|
KeyValuePair<string, string> string_kv2 = new KeyValuePair<string, string>("key2", "second");
|
|
|
KeyValuePair<string, string> string_kv3 = new KeyValuePair<string, string>("key3", "third");
|
|
|
|
|
|
IDictionary<string, string> stringDic = new Dictionary<string, string>();
|
|
|
stringDic.Add("key1", "first");
|
|
|
stringDic.Add("key2", "second");
|
|
|
stringDic.Add("key3", "third");
|
|
|
|
|
|
Assert.Contains<string, string>("key1", stringDic);
|
|
|
Assert.Contains<KeyValuePair<string, string>>(sring_kv1, stringDic);
|
|
|
|
|
|
//数字
|
|
|
KeyValuePair<string, int> int_kv1 = new KeyValuePair<string, int>("key1", 1);
|
|
|
KeyValuePair<string, int> int_kv2 = new KeyValuePair<string, int>("key2", 2);
|
|
|
KeyValuePair<string, int> int_kv3 = new KeyValuePair<string, int>("key3", 3);
|
|
|
|
|
|
IDictionary<string, int> intDic = new Dictionary<string, int>();
|
|
|
intDic.Add("key1", 1);
|
|
|
intDic.Add("key2", 2);
|
|
|
intDic.Add("key3", 3);
|
|
|
|
|
|
Assert.Contains<string, int>("key1", intDic);
|
|
|
Assert.Contains<KeyValuePair<string, int>>(int_kv1, intDic);
|
|
|
|
|
|
//类
|
|
|
Person person1 = new Person() { Id = 1, FirstName = "first1", LastName = "last1" };
|
|
|
Person person2 = new Person() { Id = 2, FirstName = "first2", LastName = "last2" };
|
|
|
Person person3 = new Person() { Id = 3, FirstName = "first3", LastName = "last3" };
|
|
|
|
|
|
KeyValuePair<string, Person> class_kv1 = new KeyValuePair<string, Person>("key1", person1);
|
|
|
KeyValuePair<string, Person> class_kv2 = new KeyValuePair<string, Person>("key2", person2);
|
|
|
KeyValuePair<string, Person> class_kv3 = new KeyValuePair<string, Person>("key3", person3);
|
|
|
|
|
|
IDictionary<string, Person> classDic = new Dictionary<string, Person>();
|
|
|
classDic.Add("key1", person1);
|
|
|
classDic.Add("key2", person2);
|
|
|
classDic.Add("key3", person3);
|
|
|
|
|
|
Assert.Contains<string, Person>("key1", classDic);
|
|
|
Assert.Contains<KeyValuePair<string, Person>>(class_kv1, classDic);
|
|
|
Assert.Contains(class_kv2, classDic);
|
|
|
Assert.Contains(class_kv3, classDic);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Contains_Generic_In_IReadOnlyDictionary_Test()
|
|
|
{
|
|
|
//类似 IDictionary
|
|
|
|
|
|
//字符串
|
|
|
KeyValuePair<string, string> sring_kv1 = new KeyValuePair<string, string>("key1", "first");
|
|
|
KeyValuePair<string, string> string_kv2 = new KeyValuePair<string, string>("key2", "second");
|
|
|
KeyValuePair<string, string> string_kv3 = new KeyValuePair<string, string>("key3", "third");
|
|
|
|
|
|
IDictionary<string, string> stringDic = new Dictionary<string, string>();
|
|
|
stringDic.Add("key1", "first");
|
|
|
stringDic.Add("key2", "second");
|
|
|
stringDic.Add("key3", "third");
|
|
|
|
|
|
IReadOnlyDictionary<string, string> stringReadOnlyDic = stringDic as IReadOnlyDictionary<string, string>;
|
|
|
|
|
|
Assert.Contains<string, string>("key1", stringReadOnlyDic);
|
|
|
Assert.Contains<KeyValuePair<string, string>>(sring_kv1, stringReadOnlyDic);
|
|
|
|
|
|
//类
|
|
|
Person person1 = new Person() { Id = 1, FirstName = "first1", LastName = "last1" };
|
|
|
Person person2 = new Person() { Id = 2, FirstName = "first2", LastName = "last2" };
|
|
|
Person person3 = new Person() { Id = 3, FirstName = "first3", LastName = "last3" };
|
|
|
|
|
|
KeyValuePair<string, Person> class_kv1 = new KeyValuePair<string, Person>("key1", person1);
|
|
|
KeyValuePair<string, Person> class_kv2 = new KeyValuePair<string, Person>("key2", person2);
|
|
|
KeyValuePair<string, Person> class_kv3 = new KeyValuePair<string, Person>("key3", person3);
|
|
|
|
|
|
IDictionary<string, Person> classDic = new Dictionary<string, Person>();
|
|
|
classDic.Add("key1", person1);
|
|
|
classDic.Add("key2", person2);
|
|
|
classDic.Add("key3", person3);
|
|
|
|
|
|
IReadOnlyDictionary<string, Person> classReadOnlyDic = classDic as IReadOnlyDictionary<string, Person>;
|
|
|
|
|
|
Assert.Contains<string, Person>("key1", classReadOnlyDic);
|
|
|
Assert.Contains<KeyValuePair<string, Person>>(class_kv1, classReadOnlyDic);
|
|
|
Assert.Contains(class_kv2, classReadOnlyDic);
|
|
|
Assert.Contains(class_kv3, classReadOnlyDic);
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region DoesNotContain 类似Contain 略过
|
|
|
#endregion
|
|
|
|
|
|
#region InRange
|
|
|
|
|
|
[Fact]
|
|
|
public void InRange_Test()
|
|
|
{
|
|
|
Assert.InRange(5, 1, 10);
|
|
|
Assert.InRange("b", "a", "d");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void InRange_IComparable_Test()
|
|
|
{
|
|
|
IComparer<Person> comparer = new Person();
|
|
|
|
|
|
Person person1 = new Person() { Id = 1 };
|
|
|
Person person2 = new Person() { Id = 2 };
|
|
|
Person person3 = new Person() { Id = 3 };
|
|
|
|
|
|
Assert.InRange(person2, person1, person3, comparer);
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region NotInRange
|
|
|
[Fact]
|
|
|
public void NotInRange_Test()
|
|
|
{
|
|
|
Assert.NotInRange<int>(5, 10, 100);
|
|
|
Assert.NotInRange(20, 100, 2000);
|
|
|
Assert.NotInRange("a", "b", "d");
|
|
|
Assert.NotInRange("z", "b", "d");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotInRange_IComparable_Test()
|
|
|
{
|
|
|
IComparer<Person> comparer = new Person();
|
|
|
|
|
|
Person person1 = new Person() { Id = 1 };
|
|
|
Person person2 = new Person() { Id = 2 };
|
|
|
Person person3 = new Person() { Id = 3 };
|
|
|
|
|
|
Assert.NotInRange(person1, person2, person3, comparer);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region Throws
|
|
|
[Fact]
|
|
|
public void Throws_Func_Test()
|
|
|
{
|
|
|
//方法不推荐使用:用泛型版本替代
|
|
|
var result = Assert.Throws(typeof(ArgumentNullException), () => { ArgumentNullException ex = new ArgumentNullException("userName"); throw ex; return ex; });
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Throws_Action_Test()
|
|
|
{
|
|
|
//方法不推荐使用:用泛型版本替代
|
|
|
var result = Assert.Throws(typeof(FormatException), () => decimal.Parse("abc"));
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public async Task Throws_Async_Test()
|
|
|
{
|
|
|
//方法不推荐使用:用泛型版本替代
|
|
|
var result = await Assert.ThrowsAsync(typeof(FormatException), () => { return Task.Run(() => { int.Parse("abc"); }); });
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Throws_Generic_Func_Test()
|
|
|
{
|
|
|
var result = Assert.Throws<FormatException>(() => ThrowAndReturnFormatException());
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Throws_Generic_Action_Test()
|
|
|
{
|
|
|
var result = Assert.Throws<FormatException>(() => ThrowFormatException());
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Throws_Generic_ParamName_Func_Test()
|
|
|
{
|
|
|
var paramName = "userName";
|
|
|
var result = Assert.Throws<ArgumentNullException>(paramName, () => ThrowAndReturnArgumentNullException(paramName));
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Throws_Generic_ParamName_Action_Test()
|
|
|
{
|
|
|
var paramName = "userName";
|
|
|
var result = Assert.Throws<ArgumentNullException>(paramName, () => ThrowArgumentNullException(paramName));
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public async Task Throws_Generic_Func_Async_Test()
|
|
|
{
|
|
|
var reslut = await Assert.ThrowsAsync<FormatException>(() => ThrowAndReturnFormatExceptionAsync());
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public async Task Throws_Generic_ParamName_Async_Test()
|
|
|
{
|
|
|
var paramName = "userName";
|
|
|
var reslut = await Assert.ThrowsAsync<ArgumentNullException>(paramName, () => ThrowAndReturnArgumentNullExceptionAsync(paramName));
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void ThrowsAny_Func_Test()
|
|
|
{
|
|
|
var result = Assert.ThrowsAny<FormatException>(() => ThrowAndReturnFormatException());
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 断言异常或派生类异常
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void ThrowsAny_Action_Test()
|
|
|
{
|
|
|
var result = Assert.ThrowsAny<FormatException>(() => ThrowFormatException());
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public async Task ThrowsAny_Func_Async_Test()
|
|
|
{
|
|
|
var result = await Assert.ThrowsAnyAsync<FormatException>(() => ThrowAndReturnFormatExceptionAsync());
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NotThrow_Exception_Test()
|
|
|
{
|
|
|
//2.0及更高版本,移除了 NotThrow断言
|
|
|
//使用TryCatch替代或自定断言扩展
|
|
|
|
|
|
Exception exception = null;
|
|
|
try
|
|
|
{
|
|
|
//dosomething
|
|
|
exception = null;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
exception = ex;
|
|
|
}
|
|
|
|
|
|
Assert.Null(exception);
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region Matches
|
|
|
[Fact]
|
|
|
public void Matches_String_Test()
|
|
|
{
|
|
|
//用户名正则:大小写字线、数字、下划线组成,6-16位长度
|
|
|
var userNameReg = @"^[a-zA-Z]\w{5,15}$";
|
|
|
Assert.Matches(userNameReg, "bicijinlian");
|
|
|
Assert.Matches(userNameReg, "wangerxiao_1981");
|
|
|
|
|
|
//email正则
|
|
|
var emailReg = @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$";
|
|
|
Assert.Matches(emailReg, "bicijinlian@163.com");
|
|
|
Assert.Matches(emailReg, "wangerxiao_1981@126.com");
|
|
|
Assert.Matches(emailReg, "15601716045@126.com");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void DoesNotMatch_String_Test()
|
|
|
{
|
|
|
//用户名正则:大小写字线、数字、下划线组成,6-16位长度
|
|
|
var userNameReg = @"^[a-zA-Z]\w{5,15}$";
|
|
|
Assert.DoesNotMatch(userNameReg, "abcd0123456789abcdefg");
|
|
|
Assert.DoesNotMatch(userNameReg, "wang");
|
|
|
Assert.DoesNotMatch(userNameReg, "bicijinlian$");
|
|
|
Assert.DoesNotMatch(userNameReg, "wangerxiao_1981@163");
|
|
|
|
|
|
//email正则
|
|
|
var emailReg = @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$";
|
|
|
Assert.DoesNotMatch(emailReg, "bicijinlian");
|
|
|
Assert.DoesNotMatch(emailReg, "wangerxiao_1981@126");
|
|
|
Assert.DoesNotMatch(emailReg, "15601716045126.com");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Matches_Regex_Test()
|
|
|
{
|
|
|
//用户名正则:大小写字线、数字、下划线组成,6-16位长度
|
|
|
var userNameReg = new System.Text.RegularExpressions.Regex(@"^[a-zA-Z]\w{5,15}$");
|
|
|
Assert.Matches(userNameReg, "bicijinlian");
|
|
|
Assert.Matches(userNameReg, "wangerxiao_1981");
|
|
|
|
|
|
//email正则
|
|
|
var emailReg = new System.Text.RegularExpressions.Regex(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
|
|
|
Assert.Matches(emailReg, "bicijinlian@163.com");
|
|
|
Assert.Matches(emailReg, "wangerxiao_1981@126.com");
|
|
|
Assert.Matches(emailReg, "15601716045@126.com");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void DoesNotMatch_Regex_Test()
|
|
|
{
|
|
|
//用户名正则:大小写字线、数字、下划线组成,6-16位长度
|
|
|
var userNameReg = new System.Text.RegularExpressions.Regex(@"^[a-zA-Z]\w{5,15}$");
|
|
|
Assert.DoesNotMatch(userNameReg, "abcd0123456789abcdefg");
|
|
|
Assert.DoesNotMatch(userNameReg, "wang");
|
|
|
Assert.DoesNotMatch(userNameReg, "bicijinlian$");
|
|
|
Assert.DoesNotMatch(userNameReg, "wangerxiao_1981@163");
|
|
|
|
|
|
//email正则
|
|
|
var emailReg = new System.Text.RegularExpressions.Regex(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
|
|
|
Assert.DoesNotMatch(emailReg, "bicijinlian");
|
|
|
Assert.DoesNotMatch(emailReg, "wangerxiao_1981@126");
|
|
|
Assert.DoesNotMatch(emailReg, "15601716045126.com");
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region StartWith | EndWith
|
|
|
[Fact]
|
|
|
public void StartsWith_Test()
|
|
|
{
|
|
|
Assert.StartsWith("Start", "StartAndEnd");
|
|
|
Assert.StartsWith("start", "StartAndEnd", StringComparison.CurrentCultureIgnoreCase);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void EndsWith_Test()
|
|
|
{
|
|
|
Assert.EndsWith("end", "startAndend");
|
|
|
Assert.EndsWith("end", "StartAndEnd", StringComparison.CurrentCultureIgnoreCase);
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Single
|
|
|
[Fact]
|
|
|
public void Single_Collection_Test()
|
|
|
{
|
|
|
//只有一项的集合
|
|
|
|
|
|
List<string> stringArray = new List<string>() { "first" };
|
|
|
Assert.Single(stringArray);
|
|
|
|
|
|
List<decimal> decimalArray = new List<decimal>() { 5.66M };
|
|
|
Assert.Single(decimalArray);
|
|
|
|
|
|
List<Person> classArray = new List<Person>() { new Person() { Id = 2 } };
|
|
|
Assert.Single(classArray);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 集合中,指定项没有重复项
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Single_Collection_Expected_Test()
|
|
|
{
|
|
|
//集合中,指定的项只有一个,即是指定项在集合中没有重复项
|
|
|
//不被指定的项,可以有多个
|
|
|
|
|
|
List<string> stringArray = new List<string>() { "first", "second", "second" };
|
|
|
|
|
|
Assert //如果换成:List<string> stringArray = new List<string>() { "first","second","first" }
|
|
|
//因为"first"有两项,则断言失败
|
|
|
.Single(stringArray, "first");
|
|
|
|
|
|
List<decimal> decimalArray = new List<decimal>() { 5.66M, 7.7M, 8.8M };
|
|
|
Assert.Single(decimalArray, 5.66M);
|
|
|
|
|
|
Person person1 = new Person() { Id = 1 };
|
|
|
Person person2 = new Person() { Id = 2 };
|
|
|
Person person3 = new Person() { Id = 2 };
|
|
|
List<Person> classArray = new List<Person>() { person1, person2 };
|
|
|
Assert.Single(classArray, person1);
|
|
|
|
|
|
List<Person> classArray2 = new List<Person>() { person1, person2, person3 };
|
|
|
Assert.True(true, "person2和person3是相同的项,所以 Assert.Single(classArray, person2) 会失败");
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Single_Generic_Test()
|
|
|
{
|
|
|
//只有一项的集合(推荐简化写法)
|
|
|
|
|
|
List<string> stringArray = new List<string>() { "first" };
|
|
|
Assert.Single<string>(stringArray);
|
|
|
|
|
|
List<decimal> decimalArray = new List<decimal>() { 5.66M };
|
|
|
Assert.Single<decimal>(decimalArray);
|
|
|
|
|
|
List<Person> classArray = new List<Person>() { new Person() { Id = 2 } };
|
|
|
Assert.Single<Person>(classArray);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void Single_Generic_Predicate_Test()
|
|
|
{
|
|
|
//集合中,指定表达式的项只有一个,即是Predicate<>筛选结果在集合中没有重复项
|
|
|
//不被指定的项,可以有多个
|
|
|
|
|
|
List<string> stringArray = new List<string>() { "first", "second", "second" };
|
|
|
|
|
|
Assert //如果换成:List<string> stringArray = new List<string>() { "first","second","first" }
|
|
|
//因为"first"有两项,则断言失败
|
|
|
.Single<string>(stringArray, s => s.StartsWith("f"));
|
|
|
|
|
|
List<decimal> decimalArray = new List<decimal>() { 5.66M, 7.7M, 8.8M };
|
|
|
Assert.Single(decimalArray, d => d > 8);
|
|
|
|
|
|
Person person1 = new Person() { Id = 1 };
|
|
|
Person person2 = new Person() { Id = 2 };
|
|
|
Person person3 = new Person() { Id = 2 };
|
|
|
|
|
|
List<Person> classArray = new List<Person>() { person1, person2, person3 };
|
|
|
|
|
|
Assert.Single(classArray, p => p.Id == 1);
|
|
|
|
|
|
//Assert.Single(classArray, p => p.Id == 2),则失败
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
[Fact]
|
|
|
public void All_Test()
|
|
|
{
|
|
|
List<string> items = new List<string>() { "abc", "ac", "ad", "adddeddd" };
|
|
|
Assert.All<string>(items, f => f.StartsWith("a"));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 相当于集合的自定义断言,实用意义不大
|
|
|
/// (Action<T>参数中自定义代码)
|
|
|
/// 看源代码,可能是集合类断言的基类
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Collection_Test()
|
|
|
{
|
|
|
//验证集合是否包含给定元素数量,满足元素检查器提供的条件。
|
|
|
|
|
|
List<string> list = new List<string>() { "first", "second" };
|
|
|
//参数Action<T>[] elementInspectors,元素检查器,依次检查每个元素。
|
|
|
//元素检查器的总数必须与集合中元素的数量完全匹配
|
|
|
|
|
|
//看源代码:每个Action<T>执行时,均不抛出异常,则断言通过
|
|
|
Action<string>[] actions = new Action<string>[2]
|
|
|
{
|
|
|
new Action<string> (s=> {} ),
|
|
|
new Action<string> (s=>{}),
|
|
|
};
|
|
|
|
|
|
Assert.Collection(list, actions);
|
|
|
}
|
|
|
|
|
|
#region ISet(集合)
|
|
|
/// <summary>
|
|
|
/// 子集断言
|
|
|
/// ISet是集合接口:包含不重复元素,实际集合的交、并、子集等运算
|
|
|
/// 实现了ISet接口的集合:HashSet和SortedSet
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Subset_Test()
|
|
|
{
|
|
|
//"真实值"是"期望值"的子集
|
|
|
|
|
|
HashSet<string> hset = new HashSet<string>() { "first", "second", "third" };
|
|
|
HashSet<string> sub1 = new HashSet<string>() { "first", "second" };
|
|
|
HashSet<string> sub2 = new HashSet<string>() { "second", "third" };
|
|
|
|
|
|
//expectedSuperset 期望超集,真实值是子集
|
|
|
Assert.Subset(expectedSuperset: hset, actual: sub1);
|
|
|
Assert.Subset(hset, sub2);
|
|
|
|
|
|
//自己是自己子集
|
|
|
Assert.Subset(hset, hset);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 超集断言
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Superset_Test()
|
|
|
{
|
|
|
//"真实值"是"期望值"的超集
|
|
|
|
|
|
HashSet<string> hset = new HashSet<string>() { "first", "second", "third" };
|
|
|
HashSet<string> sub1 = new HashSet<string>() { "first", "second" };
|
|
|
HashSet<string> sub2 = new HashSet<string>() { "second", "third" };
|
|
|
|
|
|
//expectedSuperset 期望超集,真实值是子集
|
|
|
Assert.Superset(sub1, hset);
|
|
|
Assert.Superset(sub2, hset);
|
|
|
|
|
|
//自己是自己子的超集
|
|
|
Assert.Superset(hset, hset);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 真子集断言
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void ProperSubset_Test()
|
|
|
{
|
|
|
//"真实值"是"期望值"的真子集
|
|
|
|
|
|
HashSet<string> hset = new HashSet<string>() { "first", "second", "third" };
|
|
|
HashSet<string> sub1 = new HashSet<string>() { "first", "second" };
|
|
|
HashSet<string> sub2 = new HashSet<string>() { "second", "third" };
|
|
|
|
|
|
//expectedSuperset 期望超集,真实值是子集
|
|
|
Assert.ProperSubset(expectedSuperset: hset, actual: sub1);
|
|
|
Assert.ProperSubset(hset, sub2);
|
|
|
|
|
|
//自己不是自己真子集
|
|
|
//Assert.ProperSubset(hset, hset);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 真超集断言
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void ProperSuperset_Test()
|
|
|
{
|
|
|
//"真实值"是"期望值"的真超集
|
|
|
|
|
|
HashSet<string> hset = new HashSet<string>() { "first", "second", "third" };
|
|
|
HashSet<string> sub1 = new HashSet<string>() { "first", "second" };
|
|
|
HashSet<string> sub2 = new HashSet<string>() { "second", "third" };
|
|
|
|
|
|
//expectedSuperset 期望超集,真实值是子集
|
|
|
Assert.ProperSuperset(sub1, hset);
|
|
|
Assert.ProperSuperset(sub2, hset);
|
|
|
|
|
|
//自己不是自己子的真超集
|
|
|
//Assert.ProperSuperset(hset, hset);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 事件(暂未实现)
|
|
|
|
|
|
/// <summary>
|
|
|
/// 属性更改事件
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void PropertyChanged_Test()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 属性更改事件(异步)
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void PropertyChangedAsync_Test()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 断言 特定事件被触发
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void Raises_Test()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 断言 事件或派生事件 被触发
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void RaisesAny_Test()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 断言 特定事件被触发(异步)
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void RaisesAsync_Test()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 断言 事件或派生事件 被触发(异步)
|
|
|
/// </summary>
|
|
|
[Fact]
|
|
|
public void RaisesAnyAsync_Test()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 私有方法
|
|
|
|
|
|
private void ThrowArgumentNullException(string paramName)
|
|
|
{
|
|
|
ArgumentNullException ex = new ArgumentNullException(paramName, "message");
|
|
|
throw ex;
|
|
|
}
|
|
|
|
|
|
private ArgumentNullException ThrowAndReturnArgumentNullException(string paramName)
|
|
|
{
|
|
|
ArgumentNullException ex = new ArgumentNullException(paramName, "message");
|
|
|
throw ex;
|
|
|
}
|
|
|
|
|
|
private async Task<ArgumentNullException> ThrowAndReturnArgumentNullExceptionAsync(string paramName)
|
|
|
{
|
|
|
Func<string, ArgumentNullException> func = (para) =>
|
|
|
{
|
|
|
ArgumentNullException ex = new ArgumentNullException(paramName, "message");
|
|
|
throw ex;
|
|
|
};
|
|
|
var reslut = await Task.Run(() => func(paramName));
|
|
|
return reslut;
|
|
|
}
|
|
|
|
|
|
private void ThrowFormatException()
|
|
|
{
|
|
|
int.Parse("ping");
|
|
|
}
|
|
|
|
|
|
private FormatException ThrowAndReturnFormatException()
|
|
|
{
|
|
|
FormatException exception = null;
|
|
|
try
|
|
|
{
|
|
|
int.Parse("ping");
|
|
|
}
|
|
|
catch (FormatException ex)
|
|
|
{
|
|
|
exception = ex;
|
|
|
throw ex;
|
|
|
}
|
|
|
|
|
|
return exception;
|
|
|
}
|
|
|
|
|
|
private async Task ThrowFormatExceptionAsync()
|
|
|
{
|
|
|
await Task.Run(() => { int.Parse("ping"); });
|
|
|
}
|
|
|
|
|
|
private async Task ThrowAndReturnFormatExceptionAsync()
|
|
|
{
|
|
|
Func<FormatException> func = () =>
|
|
|
{
|
|
|
int.Parse("ping");
|
|
|
return new FormatException();
|
|
|
};
|
|
|
|
|
|
await Task.Run(() => func());
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region 清理
|
|
|
public void Dispose()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
}
|
|
|
}
|