XUnit 依賴注入

XUnit 依賴注入

Intro

現(xiàn)在的開發(fā)中越來(lái)越看重依賴注入的思想腾夯,微軟的 Asp.Net Core 框架更是天然集成了依賴注入,那么在單元測(cè)試中如何使用依賴注入呢既棺?

本文主要介紹如何通過 XUnit 來(lái)實(shí)現(xiàn)依賴注入璃吧, XUnit 主要借助 SharedContext 來(lái)共享一部分資源包括這些資源的創(chuàng)建以及釋放饮怯。

Scoped

針對(duì) Scoped 的對(duì)象可以借助 XUnit 中的 IClassFixture 來(lái)實(shí)現(xiàn)

  1. 定義自己的 Fixture,需要初始化的資源在構(gòu)造方法里初始化榛泛,如果需要在測(cè)試結(jié)束的時(shí)候釋放資源需要實(shí)現(xiàn) IDisposable 接口
  2. 需要依賴注入的測(cè)試類實(shí)現(xiàn)接口 IClassFixture<Fixture>
  3. 在構(gòu)造方法中注入實(shí)現(xiàn)的 Fixture 對(duì)象蝌蹂,并在構(gòu)造方法中使用 Fixture 對(duì)象中暴露的公共成員

Singleton

針對(duì) Singleton 的對(duì)象可以借助 XUnit 中的 ICollectionFixture 來(lái)實(shí)現(xiàn)

  1. 定義自己的 Fixture,需要初始化的資源在構(gòu)造方法里初始化曹锨,如果需要在測(cè)試結(jié)束的時(shí)候釋放資源需要實(shí)現(xiàn) IDisposable 接口
  2. 創(chuàng)建 CollectionDefinition孤个,實(shí)現(xiàn)接口 ICollectionFixture<Fixture>,并添加一個(gè) [CollectionDefinition("CollectionName")] Attribute艘希,CollectionName 需要在整個(gè)測(cè)試中唯一硼身,不能出現(xiàn)重復(fù)的 CollectionName
  3. 在需要注入的測(cè)試類中添加 [Collection("CollectionName")] Attribute,然后在構(gòu)造方法中注入對(duì)應(yīng)的 Fixture

Tips

  • 如果有多個(gè)類需要依賴注入覆享,可以通過一個(gè)基類來(lái)做佳遂,這樣就只需要一個(gè)基類上添加 [Collection("CollectionName")] Attribute,其他類只需要集成這個(gè)基類就可以了

Samples

Scoped Sample

這里直接以 XUnit 的示例為例:

public class DatabaseFixture : IDisposable
{
    public DatabaseFixture()
    {
        Db = new SqlConnection("MyConnectionString");

        // ... initialize data in the test database ...
    }

    public void Dispose()
    {
        // ... clean up test data from the database ...
    }

    public SqlConnection Db { get; private set; }
}

public class MyDatabaseTests : IClassFixture<DatabaseFixture>
{
    DatabaseFixture fixture;

    public MyDatabaseTests(DatabaseFixture fixture)
    {
        this.fixture = fixture;
    }


    [Fact]
    public async Task GetTest()
    {
        // ... write tests, using fixture.Db to get access to the SQL Server ...
        // ... 在這里使用注入 的 DatabaseFixture
    }
}

Singleton Sample

這里以一個(gè)對(duì) Controller 測(cè)試的測(cè)試為例

  1. 自定義 Fixture

        /// <summary>
        /// A test fixture which hosts the target project (project we wish to test) in an in-memory server.
        /// </summary>
        public class TestStartupFixture : IDisposable
        {
            private readonly IWebHost _server;
            public IServiceProvider Services { get; }
    
            public HttpClient Client { get; }
    
            public string ServiceBaseUrl { get; }
    
            public TestStartupFixture()
            {
                var builder = WebHost.CreateDefaultBuilder()
                    .UseUrls($"http://localhost:{GetRandomPort()}")
                    .UseStartup<TestStartup>();
    
                _server = builder.Build();
                _server.Start();
    
                var url = _server.ServerFeatures.Get<IServerAddressesFeature>().Addresses.First();
                Services = _server.Services;
                ServiceBaseUrl = $"{url}/api/";
    
                Client = new HttpClient()
                {
                    BaseAddress = new Uri(ServiceBaseUrl)
                };
    
                Initialize();
            }
    
            /// <summary>
            /// TestDataInitialize
            /// </summary>
            private void Initialize()
            {
                // ...
            }
    
            public void Dispose()
            {
                Client.Dispose();
                _server.Dispose();
            }
    
            private static readonly Random Random = new Random();
    
            private static int GetRandomPort()
            {
                var activePorts = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners().Select(_ => _.Port).ToList();
    
                var randomPort = Random.Next(10000, 65535);
    
                while (activePorts.Contains(randomPort))
                {
                    randomPort = Random.Next(10000, 65535);
                }
    
                return randomPort;
            }
        }
    
  2. 自定義Collection

        [CollectionDefinition("TestCollection")]
        public class TestCollection : ICollectionFixture<TestStartupFixture>
        {
        }
    
  3. 自定義一個(gè) TestBase

        [Collection("TestCollection")]
        public class ControllerTestBase
        {
            protected readonly HttpClient Client;
            protected readonly IServiceProvider ServiceProvider;
    
            public ControllerTestBase(TestStartupFixture fixture)
            {
                Client = fixture.Client;
                ServiceProvider = fixture.Services;
            }
        }
    
  4. 需要依賴注入的Test類寫法

    public class AttendancesTest : ControllerTestBase
    {
        public AttendancesTest(TestStartupFixture fixture) : base(fixture)
        {
        }

        [Fact]
        public async Task GetAttendances()
        {
            var response = await Client.GetAsync("attendances");
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);

            response = await Client.GetAsync("attendances?type=1");
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        }
    }

Reference

Contact

如果您有什么問題撒顿,歡迎隨時(shí)聯(lián)系我

Contact me: weihanli@outlook.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末丑罪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凤壁,更是在濱河造成了極大的恐慌吩屹,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拧抖,死亡現(xiàn)場(chǎng)離奇詭異煤搜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)唧席,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門擦盾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人淌哟,你說我怎么就攤上這事迹卢。” “怎么了徒仓?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵腐碱,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我掉弛,道長(zhǎng)症见,這世上最難降的妖魔是什么喂走? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮筒饰,結(jié)果婚禮上缴啡,老公的妹妹穿的比我還像新娘。我一直安慰自己瓷们,他們只是感情好业栅,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谬晕,像睡著了一般碘裕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上攒钳,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天帮孔,我揣著相機(jī)與錄音,去河邊找鬼不撑。 笑死文兢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的焕檬。 我是一名探鬼主播姆坚,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼实愚!你這毒婦竟也來(lái)了兼呵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤腊敲,失蹤者是張志新(化名)和其女友劉穎击喂,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碰辅,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡懂昂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了没宾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忍法。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖榕吼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情勉失,我是刑警寧澤羹蚣,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站乱凿,受9級(jí)特大地震影響顽素,放射性物質(zhì)發(fā)生泄漏咽弦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一胁出、第九天 我趴在偏房一處隱蔽的房頂上張望型型。 院中可真熱鬧,春花似錦全蝶、人聲如沸闹蒜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)绷落。三九已至,卻和暖如春始苇,著一層夾襖步出監(jiān)牢的瞬間砌烁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工催式, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留函喉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓荣月,卻偏偏與公主長(zhǎng)得像管呵,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子喉童,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理撇寞,服務(wù)發(fā)現(xiàn),斷路器堂氯,智...
    卡卡羅2017閱讀 134,711評(píng)論 18 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架蔑担,建立于...
    Hsinwong閱讀 22,442評(píng)論 1 92
  • 原文地址:http://www.reibang.com/p/70151fc0ef5d Zookeeper客戶端C...
    cn_yaojin閱讀 943評(píng)論 0 0
  • (南汝:這個(gè)故事是通過兩個(gè)人的內(nèi)心想法寫的,并又所借鑒咽白,可能寫的不好啤握,寫的有點(diǎn)長(zhǎng),但我就很想寫下它晶框。) --我……...
    南宮沉閱讀 224評(píng)論 0 2
  • 今天收到她的信息:“姐排抬,我的房貸還清了”。這是她的第二套房授段。 1. 她姐妹3人蹲蒲,父母是下崗工人,她排行第二侵贵,是家里...
    mimi播報(bào)閱讀 389評(píng)論 6 6