xUnit支持两种不同类型的单元测试,事实[Fact]和理论[Theory]。 当我们无论数据怎样变化总有一些标准总是必须符合时我们使用xUnit Fact。 例如,当我们测试一个业务流程。 而xUnit理论依赖于一组参数及其数据,我们将参数和数据传递给测试方法, 我们根据特定数据来判断测试结果时我们使用xUnit Theory。xUnit Theory 支持3种数据传递方式InlineData、MemberData 和 ClassData。
InlineData
我们使用Fact一般是这样:
[Fact]
public void TestAdd()
{
Assert.Equal(5, Add(2, 3));
Assert.Equal(7, Add(2, 5));
Assert.Equal(10, Add(4, 6));
}
复制代码
多个数据的话代码重复,那么使用InlineData则变成了这样:
[Theory]
[InlineData(5, 2, 3)]
[InlineData(7, 2, 5)]
[InlineData(10, 5, 5)]
public void TestAddUseInlineData(int sum, int a, int b)
{
Assert.Equal(sum, Add(a, b));
}
复制代码
正如上面的代码,我们在InlineData中提供了一些值,xUnit将创建多个测试,并且每次都将测试用例参数填充到InlineData中。 但是InlineData属性中传递有很多限制,只能传递简单类型,我们如果想要传递更复杂的参数可以使用MemberData 和 ClassData。
ClassData
ClassData是Theory的第二种传递参数的方式,虽然更复杂但是传递时也更方便。以下示例是一个测试判断用户是否输入了手机号码的方法
public class TestsUseClassData
{
public bool HasMobile(Person person)
{
return !string.IsNullOrWhiteSpace(person.Mobile);
}
[Theory]
[ClassData(typeof(DataForTest))]//使用ClassData将数据传递给Theory
public void IndexOf(Person person, bool hasMobile)
{
Assert.Equal(hasMobile, HasMobile(person));
}
}
/// <summary>
/// 在这里我创建了一个继承自IEnumerable <object []>的类,注意它必须是一个对象,
/// 否则xUnit会抛出一个错误。
/// </summary>
public class DataForTest : IEnumerable<object[]>
{
//这里是我们传递给Theory的数据
private readonly List<object[]> _data = new List<object[]>
{
new object[] { new Person() { Id=1,Name="周三"},false },
new object[] { new Person() { Id=2,Name="王石", Mobile = "139XXXXXXXX"},true },
new object[] { new Person() { Id=3,Name="赵坎", Mobile = ""},false },
};
public IEnumerator<object[]> GetEnumerator()
{ return _data.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator()
{ return GetEnumerator(); }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Mobile { get; set; }
}
复制代码
您可以实际跑跑上面的代码,下面我们看看MemberData的使用。
MemberData
MemberData同样可以传递复杂类型参数,而且我们不必创建一个类来承载它,示例如下:
public class TestsUseMemberData
{
public bool HasMobile(Person person)
{
return !string.IsNullOrWhiteSpace(person.Mobile);
}
//传递数据给Theory的方法
public static IEnumerable<object[]> GetTestData()
{
yield return new object[] { new Person() { Id = 1, Name = "周三" }, false };
yield return new object[] { new Person() { Id = 2, Name = "王石", Mobile = "139XXXXXXXX" }, true };
yield return new object[] { new Person() { Id = 3, Name = "赵坎", Mobile = "" }, false };
}
[Theory]
[MemberData(nameof(GetTestData))]//使用MemberData将数据传递给Theory
public void IndexOf(Person person, bool hasMobile)
{
Assert.Equal(hasMobile, HasMobile(person));
}
}
复制代码