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
{
    /// <summary>
    /// Collection级别的Fixture
    /// 测试程序集中所有测试类可以共享
    /// </summary>
    [Collection("Demo Collection")]
    public class UseICollectionFixtureTest
    {
        /* 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()方法 --> 结束测试类实例 --> 完成

         *   ........

         *  本测试类中所有用例完成

         *  清理共享实例
         * 
         *  其它测试类y m n a ......
         *  
         *  ..........
         *  
         *  所有测试类完成
         *  
         *  ICollectionFixture共享实例,清理
         *  
         *  完成
         * 
         * 特别注意:
         * 由于测试用例执行顺序不固定,还可能并行运行
         * 所以对共享对象(ICollectionFixture和ClassFixture)的使用,应避免出现竞态条件。
         * 否则,很容易因共享类的竞态条件,导致单元测试失败。
         * 因此:共享资源,只适合读,不适合写,使用须谨慎。
        */
        CollectionFixtureDemo fixtureDemo;

        public UseICollectionFixtureTest(CollectionFixtureDemo fixture)
        {
            fixtureDemo = fixture;
        }

        [Fact]
        public void Test()
        {
            var persons = fixtureDemo.GetPersonById(1);

            Assert.True(persons.Id == 1, "使用全局共享对象");
        }
    }
}