diff --git a/xUnitStudy.Model/xUnitStudy.Model.csproj b/xUnitStudy.Model/xUnitStudy.Model.csproj index cf2080f..0ec04d7 100644 --- a/xUnitStudy.Model/xUnitStudy.Model.csproj +++ b/xUnitStudy.Model/xUnitStudy.Model.csproj @@ -46,7 +46,8 @@ <Compile Include="Student.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="xUnitStudy\AssertEqualDemo.cs" /> - <Compile Include="xUnitStudy\FixtureDemo.cs" /> + <Compile Include="xUnitStudy\CollectionFixtureDemo.cs" /> + <Compile Include="xUnitStudy\ClassFixtureDemo.cs" /> <Compile Include="xUnitStudy\IPerson.cs" /> <Compile Include="xUnitStudy\Person.cs" /> <Compile Include="xUnitStudy\Teacher.cs" /> diff --git a/xUnitStudy.Model/xUnitStudy/FixtureDemo.cs b/xUnitStudy.Model/xUnitStudy/ClassFixtureDemo.cs similarity index 95% rename from xUnitStudy.Model/xUnitStudy/FixtureDemo.cs rename to xUnitStudy.Model/xUnitStudy/ClassFixtureDemo.cs index 49b6ddb..3c3b045 100644 --- a/xUnitStudy.Model/xUnitStudy/FixtureDemo.cs +++ b/xUnitStudy.Model/xUnitStudy/ClassFixtureDemo.cs @@ -9,11 +9,11 @@ namespace xUnitStudy.Model /// <summary> /// 测试方法共享对象实例 /// </summary> - public class FixtureDemo : IDisposable + public class ClassFixtureDemo : IDisposable { public int CallTimes { get; private set; } public List<Person> Persons; - public FixtureDemo() + public ClassFixtureDemo() { Persons = new List<Person>() { diff --git a/xUnitStudy.Model/xUnitStudy/CollectionFixtureDemo.cs b/xUnitStudy.Model/xUnitStudy/CollectionFixtureDemo.cs new file mode 100644 index 0000000..7294f29 --- /dev/null +++ b/xUnitStudy.Model/xUnitStudy/CollectionFixtureDemo.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace xUnitStudy.Model +{ + /// <summary> + /// 测试方法共享对象实例 + /// </summary> + public class CollectionFixtureDemo : IDisposable + { + public List<Person> Persons; + + public CollectionFixtureDemo() + { + Persons = 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" }, + }; + } + + public Person GetPersonById(int personId) + { + var find = Persons.FirstOrDefault(p => p.Id == personId); + + return find; + } + + public void Dispose() + { + Persons = null; + } + } +} diff --git a/xUnitStudy.WebApi.Test/UseFixture/CollectionFixtureSetup.cs b/xUnitStudy.WebApi.Test/UseFixture/CollectionFixtureSetup.cs index 2492c1f..8a1155a 100644 --- a/xUnitStudy.WebApi.Test/UseFixture/CollectionFixtureSetup.cs +++ b/xUnitStudy.WebApi.Test/UseFixture/CollectionFixtureSetup.cs @@ -17,7 +17,7 @@ namespace xUnitStudy.WebApi.Test /// 设置全局共享 /// </summary> [CollectionDefinition("Demo Collection")] - public class CollectionFixtureSetup:ICollectionFixture<FixtureDemo> + public class CollectionFixtureSetup:ICollectionFixture<CollectionFixtureDemo> { //这个类没有代码,而不需要创建。 //其目的是简单地设置测试集共享数据 diff --git a/xUnitStudy.WebApi.Test/UseFixture/UseClassFixtureTest.cs b/xUnitStudy.WebApi.Test/UseFixture/UseClassFixtureTest.cs index 506aff7..e2546c5 100644 --- a/xUnitStudy.WebApi.Test/UseFixture/UseClassFixtureTest.cs +++ b/xUnitStudy.WebApi.Test/UseFixture/UseClassFixtureTest.cs @@ -14,16 +14,47 @@ using xUnitStudy.Model; namespace xUnitStudy.WebApi.Test { /// <summary> - /// 测试类级别的共享(类内所有测试用例,共享一个实例) - /// 注意:因为不能保证各个单元测试的执行先后顺序或者特别是并行单元测试时, - /// 很容因共享类的并发操作导致单元测试失败。共享须谨慎。 - /// 适合读,不适合写 + /// 测试类级别的共享(类内所有测试用例,共享一个类的实例) /// </summary> - public class UseIClassFixtureTest:IClassFixture<FixtureDemo>, IDisposable + public class UseIClassFixtureTest:IClassFixture<ClassFixtureDemo>, IDisposable { - FixtureDemo fixtureDemo; - - public UseIClassFixtureTest(FixtureDemo fixture) + /* IClassFixture使用步骤: + * + * 01:创建自定义的Fixture类,添加构造函数;如需做清理,则实现IDisposable接口 + * 02:创建具体的测试类,并继承 IClassFixture<T>(T 即是 自定义的Fixture类) + * 03:在测试类的构造函数中添加对应的注入参数来获取Fixture,这样的设计使得我们在测试类中所有的测试用例中共享一些Context数据. + * xUnit.Net 会自动发现和运用 + * + * 执行流程: + * + * 发现测试类 + * + * xUnit 发现测试类相关共享Fixture,创建共享实例并保存,与测试类关联 + * + * 用例b:创建测试类实例 --> 获取共享Fixture --> 构造函数 --> 用例1 --> Dispose()方法 --> 结束测试类实例 --> 完成 + * + * 用例a:创建测试类实例 --> 获取共享Fixture --> 构造函数 --> 用例2 --> Dispose()方法 --> 结束测试类实例 --> 完成 + * + * 用例x:创建测试类实例 --> 获取共享Fixture --> 构造函数 --> 用例2 --> Dispose()方法 --> 结束测试类实例 --> 完成 + * + * 用例m:创建测试类实例 --> 获取共享Fixture--> 构造函数 --> 用例2 --> Dispose()方法 --> 结束测试类实例 --> 完成 + + * ........ + + * 本测试类中所有用例完成 + + * 清理共享实例 + * + * + * 特别注意: + * 由于测试用例执行顺序不固定,还可能并行运行 + * 所以对共享的使用,应避免出现竞态条件。 + * 否则,很容易因共享类的竞态条件,导致单元测试失败。 + * 因此:共享资源,只适合读,不适合写,使用须谨慎。 + */ + ClassFixtureDemo fixtureDemo; + + public UseIClassFixtureTest(ClassFixtureDemo fixture) { this.fixtureDemo = fixture; } diff --git a/xUnitStudy.WebApi.Test/UseFixture/UseCollectionFixtureTest.cs b/xUnitStudy.WebApi.Test/UseFixture/UseCollectionFixtureTest.cs index 5eb3c3f..ff86539 100644 --- a/xUnitStudy.WebApi.Test/UseFixture/UseCollectionFixtureTest.cs +++ b/xUnitStudy.WebApi.Test/UseFixture/UseCollectionFixtureTest.cs @@ -14,14 +14,64 @@ using xUnitStudy.Model; namespace xUnitStudy.WebApi.Test { /// <summary> - /// 测试集级别的共享 + /// Collection级别的Fixture + /// 测试程序集中所有测试类可以共享 /// </summary> [Collection("Demo Collection")] public class UseICollectionFixtureTest { - FixtureDemo fixtureDemo; + /* ICollectionFixture使用步骤: + * + * 01:创建自定义的Fixture类,添加构造函数;如需做清理,则实现IDisposable接口 + * 02:创建Collection类, 添加[CollectionDefinition]特性, 并设置一个唯一名称来识别测试集合. + * 03:Collection类,实现ICollectionFixture<T>接口,T 即是“自定义的Fixture类”. + * 04:创建具体的测试类,添加[Collection]特性,指定要使用的[CollectionDefinition]的唯一名称 + * 05:如果需要在测试类中使用共享对象,只需要把它作为一个构造函数参数。xUnit.Net 会自动发现和运用。 + * + * + * 执行流程: + * + * 运行整个测试集 + * + * xUnit 发现程序集中所有相关的共享ICollectionFixture,创建共享实例并保存,与测试集关联 + * + * 发现测试类x + * + * xUnit 发现测试类相关共享Fixture,创建共享实例并保存,与测试类关联 + * + * 用例b:创建测试类实例 --> 获取共享ICollectionFixture --> 获取共享ClassFixture --> 构造函数 --> 用例1 --> Dispose()方法 --> 结束测试类实例 --> 完成 + * + * 用例a:创建测试类实例 --> 获取共享ICollectionFixture --> 获取共享ClassFixture --> 构造函数 --> 用例2 --> Dispose()方法 --> 结束测试类实例 --> 完成 + * + * 用例x:创建测试类实例 --> 获取共享ICollectionFixture --> 获取共享ClassFixture --> 构造函数 --> 用例2 --> Dispose()方法 --> 结束测试类实例 --> 完成 + * + * 用例m:创建测试类实例 --> 获取共享ICollectionFixture --> 获取共享ClassFixture --> 构造函数 --> 用例2 --> Dispose()方法 --> 结束测试类实例 --> 完成 - public UseICollectionFixtureTest(FixtureDemo fixture) + * ........ + + * 本测试类中所有用例完成 + + * 清理共享实例 + * + * 其它测试类y m n a ...... + * + * .......... + * + * 所有测试类完成 + * + * ICollectionFixture共享实例,清理 + * + * 完成 + * + * 特别注意: + * 由于测试用例执行顺序不固定,还可能并行运行 + * 所以对共享对象(ICollectionFixture和ClassFixture)的使用,应避免出现竞态条件。 + * 否则,很容易因共享类的竞态条件,导致单元测试失败。 + * 因此:共享资源,只适合读,不适合写,使用须谨慎。 + */ + CollectionFixtureDemo fixtureDemo; + + public UseICollectionFixtureTest(CollectionFixtureDemo fixture) { fixtureDemo = fixture; } @@ -29,11 +79,9 @@ namespace xUnitStudy.WebApi.Test [Fact] public void Test() { - var persons = fixtureDemo.Persons; - - //do something with persons + var persons = fixtureDemo.GetPersonById(1); - Assert.True(true, "使用全局共享对象"); + Assert.True(persons.Id == 1, "使用全局共享对象"); } } } diff --git a/xUnitStudy.WebApi.Test/UseFixture/UseFullFixtures.cs b/xUnitStudy.WebApi.Test/UseFixture/UseFullFixtures.cs new file mode 100644 index 0000000..40f4549 --- /dev/null +++ b/xUnitStudy.WebApi.Test/UseFixture/UseFullFixtures.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Xunit; +using Xunit.Abstractions; +using Xunit.Extensions; +using Xunit.Sdk; + +using xUnitStudy.Model; + +namespace xUnitStudy.WebApi.Test.UseFixture +{ + /// <summary> + /// 同时使用多种共享 + /// </summary> + [Collection("Demo Collection")] + public class UseFullFixtures : IDisposable, IClassFixture<ClassFixtureDemo> + { + CollectionFixtureDemo collectionFixture; + ClassFixtureDemo classFixture; + + public UseFullFixtures(CollectionFixtureDemo collectionDemo, ClassFixtureDemo fixtureDemo) + { + classFixture = fixtureDemo; + collectionFixture = collectionDemo; + } + + [Fact] + public void Test() + { + Assert.NotNull(classFixture); + + var person = collectionFixture.GetPersonById(2); + Assert.Equal(2, person.Id); + } + + public void Dispose() + { + //每个测试用例的清理 + } + } +} diff --git a/xUnitStudy.WebApi.Test/xUnitStudy.WebApi.Test.csproj b/xUnitStudy.WebApi.Test/xUnitStudy.WebApi.Test.csproj index 78d88ba..54edc3f 100644 --- a/xUnitStudy.WebApi.Test/xUnitStudy.WebApi.Test.csproj +++ b/xUnitStudy.WebApi.Test/xUnitStudy.WebApi.Test.csproj @@ -90,6 +90,7 @@ <Compile Include="UseFixture\UseFixtureTest.cs" /> <Compile Include="UseFixture\UseClassFixtureTest.cs" /> <Compile Include="UseFixture\UseCollectionFixtureTest.cs" /> + <Compile Include="UseFixture\UseFullFixtures.cs" /> <Compile Include="UseOutputTest.cs" /> <Compile Include="UseXUnitTest.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />