1. 程式人生 > >.net測試篇之單元測試/整合測試神器Autofixture

.net測試篇之單元測試/整合測試神器Autofixture

系列目錄

autofixture簡介

有了單元測試框架加上Moq(後面我們會用單獨章節來介紹moq),可以說測試問題基上都能搞定了.然而有了AutoFixture對單元測試來說可以說是如虎添翼,AutoFixture並且它能與moq,rhinomock等框架結合,對單元測試帶來的便捷性,可維護性和擴充套件性更是難以言表,只有用用了才知道.

說了這麼多,還沒有介紹AutoFixture是幹什麼的,其實AutoFixture就是一個假資料填充工具.

其實不論是Nunit還是Xunit都有資料填充功能,並且大部分時候都能滿足需求.然而通過我們前面的介紹就會知道有以下問題:

  • 不論是vlues註解還是TestCase註解都沒有型別約束,這就可能會造成執行時錯誤.
  • 基於註解的值都只能是Const值,如果需要複雜型別就需要定義一個型別做為Source為當前操作提供值.
  • 與Nunit和Xunit生成的填充資料相比,Autofixture可以生成符合驗證規則的資料(基於system.componentmodel.annotations名稱空間下的註解約束),這在整合測試裡幫助很大,對於有著非常複雜模型驗證的介面來說,手工製造出符合模型驗證規則的資料往往是非常痛苦的.
  • Autofixture可以生成一組符合驗證規則的資料,這樣在測試的時候增加了樣本資料的隨機性,大大提升了測試的覆蓋面.

Moq測試雖然極大方便了測試,但是也會有一些問題:

  • 對於比較複雜的web專案,往往一個業務邏輯可能要消費十個幾個甚至幾十個資料介面,如果業務不是很成熟可能需要不斷的來調整這些介面,這裡的修改同時單元測試方法也需要修改(因為這些介面多數時候是通過建構函式注入的,建構函式引數數量的變動會導致呼叫者也需要做相應調整)

  • 雖然Moq也能夠模擬類物件,但是限制非常多,我們不可能為了測試把所有的方法和屬性都加上abstract或者virtual.

而autofixture則可以很好的解決這些問題.這樣極大增加程式碼的可維護性和擴充套件性.

AutoFixture並不是對moq的替代,它只能填充物件,而不能模擬物件,但是它可以與moq框架結合實現更強大的功能.

autofixture安裝

autofixture安裝非常簡單,我們在Nuget裡搜尋autofixture,第一個就是它點選安裝即可.

關於autofixture與moq結合需要的包在後面講到的時候再安裝,這裡先略過.

AutoFixture 自動為Nunit填充資料

要使AutoFixture與Nunit結合,首先我們需要安裝特定的包.

在Nuget裡輸入AutoFixture.Nunit3,會出現以下選項

由於我們使用的是Nunit3,因此我們選擇第一個安裝.

AutoFixture還可以與Xunit結合.在Nuget裡搜尋AutoFixture.xunit2便可以搜尋到AutoFixture與Xunit結合的框架.與Xunit結果的用法與Nunit差不多,只是需要注意Xunit資料測試方法需要Theory註解.

我們新建一個名為FixtureTest並引入AutoFixture.NUnit3;名稱空間

程式碼如下

 [TestFixture]
   public class FixtureTest
    {
        [Test]
        [AutoData]
        public void FixValueTest(int a, int b)
        {
            var result = Add(a , b);
            Assert.AreEqual(a + b, result);
        }
        int Add(int x, int y)
        {
            return x + y;
        }
    }

這裡與平時的單元測試相比,多了一個AutoData註解,有了AutoData註解,AutoFixture便可以給當前測試提供值了.
我們斷點除錯一下看看a和b的值

我們可以看到a和b都被賦予了隨機的值.

我們把測試程式碼改為如下

        [Test]
        [AutoData]
        public void FixValueTest(Person p1, Person p2)
        {
            var result = Add(p1.Age , p2.Age);
            Assert.AreEqual(p1.Age + p2.Age, result);
        }

我們再斷點除錯一下看看是否有值

複雜物件它也能填充!這樣就免去了為了使用複雜物件需要額外寫很多source繁瑣.

我們把程式碼改成如下

        [Test]
        [AutoData]
        public void FixValueTest(IEnumerable<Person> people)
        {
            var ages = people.Sum(a => a.Age);
        }

我們看看此時會有什麼結果

通過監視容器可以看到,AutoFixture生成了一個包含三個元素的物件.

這簡直是太方便了,autofixture自動填充值不但減少了執行時可能的型別錯誤,還有極大的擴充套件性,如果我們在測試方法上新增其它引數,它仍然能夠自動填充.而使用Nunit自身帶的TestCase如果引數減少,裡面指定的值也要減少,否則會丟擲執行時異常.

通過以上我們可以看到,AutoFixture可以生成各種型別的物件,它可以建立集合物件對我們測試來說尤其有用,免去了手動建立的麻煩.但是我們同時也看到,基於註解的方法生成集合時只生成了三個,實際上要模擬資料庫是的資料測試一些行為我們可能需要更多的元素.這裡就需要對AutoFixture本身進行配置.這是基於註解的方法無法完成