溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

xUnit 如何編寫 ASP.NET Core 單元測(cè)試

發(fā)布時(shí)間:2021-03-08 14:39:15 來(lái)源:億速云 閱讀:180 作者:TREX 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“xUnit 如何編寫 ASP.NET Core 單元測(cè)試”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“xUnit 如何編寫 ASP.NET Core 單元測(cè)試”吧!

還記得 .NET Framework 的 ASP.NET WebForm 嗎?那個(gè)年代如果要在 Web 層做單元測(cè)試簡(jiǎn)直就是災(zāi)難啊。.NET Core 吸取教訓(xùn),在設(shè)計(jì)上考慮到了可測(cè)試性,就連 ASP.NET Core 這種 Web 或 API 應(yīng)用要做單元測(cè)試也是很方便的。其中面向接口和依賴注入在這方面起到了非常重要的作用。

本文就來(lái)手把手教你如何用 xUnit 對(duì) ASP.NET Core 應(yīng)用做單元測(cè)試。.NET Core 常用的測(cè)試工具還有 NUnit 和 MSTest,我本人習(xí)慣用 xUnit 作為測(cè)試工具,所以本文用的是 xUnit。

創(chuàng)建示例項(xiàng)目

先用 ASP.NET Core API 模板建一個(gè)應(yīng)用。

模板為我們自動(dòng)創(chuàng)建了一個(gè) ValuesController,為了方便演示,我們只留其中一個(gè) Get 方法:

public class ValuesController : ControllerBase
{
 // GET api/values/5
 [HttpGet("{id}")]
 public ActionResult<string> Get(int id)
 {
  return "value";
 }
}

然后再添加一個(gè) xUnit 單元測(cè)試項(xiàng)目:

模板自動(dòng)為我們添加好了 xUnit 引用:

<ItemGroup>
 <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
 <PackageReference Include="xunit" Version="2.4.0" />
 <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>

但要測(cè)試 ASP.NET Core 應(yīng)用還需要添加兩個(gè) NuGet 包:

Install-Package Microsoft.AspNetCore.App

Install-Package Microsoft.AspNetCore.TestHost

當(dāng)然還要引入目標(biāo)項(xiàng)目。最后的引用是這樣的:

<ItemGroup>
 <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.5" />
 <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.1" />
 <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
 <PackageReference Include="xunit" Version="2.4.0" />
 <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>

<ItemGroup>
 <ProjectReference Include="..\WebApplication1\WebApplication1.csproj" />
</ItemGroup>

添加完引用后編譯一下,確認(rèn)引用沒(méi)有問(wèn)題。

編寫單元測(cè)試

寫單元測(cè)試一般有三個(gè)步驟:Arrange,Act 和 Assert。

Arrange 是準(zhǔn)備階段,這個(gè)階段是準(zhǔn)備工作,比如模擬數(shù)據(jù)、初始化對(duì)象等;

Act 是行為階段,這個(gè)階段是用準(zhǔn)備好的數(shù)據(jù)去調(diào)用要測(cè)試的方法;

Assert 是斷定階段,就是把調(diào)用目標(biāo)方法返回的值和預(yù)期的值進(jìn)行比較,如果和預(yù)期一致說(shuō)明測(cè)試通過(guò),否則為失敗。

按照這個(gè)步驟我們來(lái)編寫一個(gè)單元測(cè)試方法,以 ValuesController 中的 Get 方法作為要測(cè)試的目標(biāo)。一般一個(gè)單元測(cè)試方法就是一個(gè)測(cè)試用例。

我們?cè)跍y(cè)試工程添加一個(gè) ValuesTests 單元測(cè)試類,然后編寫一個(gè)單元測(cè)試方法,代碼如下:

public class ValuesTests
{
 public ValuesTests()
 {
  var server = new TestServer(WebHost.CreateDefaultBuilder()
   .UseStartup<Startup>());
  Client = server.CreateClient();
 }

 public HttpClient Client { get; }

 [Fact]
 public async Task GetById_ShouldBe_Ok()
 {
  // Arrange
  var id = 1;

  // Act
  var response = await Client.GetAsync($"/api/values/{id}");

  // Assert
  Assert.Equal(HttpStatusCode.OK, response.StatusCode);
 }
}

這里我們通過(guò) TestServer 拿到一個(gè) HttpClient 對(duì)象,用它我們可以模擬 Http 請(qǐng)求。我們寫了一個(gè)非常簡(jiǎn)單的測(cè)試用例,完整演示了單元測(cè)試的 Arrange,Act 和 Assert 三個(gè)步驟。

建議單元測(cè)試的方法名使用“什么應(yīng)該是什么”的模式。比如上面的 GetById_ShouldBe_Ok,表示調(diào)用 GetById 這個(gè) API 返回的結(jié)果應(yīng)該是 OK 的,這樣一看就知道你這個(gè)測(cè)試用例是干嗎的,不需要過(guò)多的注釋。

運(yùn)行單元測(cè)試

單元測(cè)試用例寫好后,打開“Test Explore”(中文版 VS 看到的是中文),在測(cè)試方法上右擊,選擇“Run Seleted Tests”,也可以在方法代碼塊內(nèi)鼠標(biāo)右擊選擇“Run Tests”:

注意看測(cè)試方法前面圖標(biāo)的顏色,目前是藍(lán)色的,表示測(cè)試用例還沒(méi)有運(yùn)行過(guò)。

測(cè)試用例執(zhí)行結(jié)束后如果結(jié)果和預(yù)期一致就是綠色的圖標(biāo):

如果運(yùn)行結(jié)果和預(yù)期不一致就會(huì)是紅色圖標(biāo),然后你需要修改代碼直到出現(xiàn)綠色圖標(biāo)。你可以在“Test Explore”的下方看到執(zhí)行消耗的時(shí)間,也可以在 Output 窗口看到執(zhí)行的細(xì)節(jié)。

以上圖標(biāo)顏色的變化過(guò)程是:藍(lán)色,紅色,再綠色,有可能藍(lán)色經(jīng)過(guò)一次運(yùn)行就直接變成綠色,也有可能經(jīng)過(guò)很多次紅色才變成綠色。測(cè)試驅(qū)動(dòng)開發(fā)中的 BRG(藍(lán)紅綠)術(shù)語(yǔ)就是這么來(lái)的。

調(diào)試單元測(cè)試

你可以通過(guò)添加斷點(diǎn)的方式在單元測(cè)試中調(diào)試。方法很簡(jiǎn)單,在需要調(diào)試的方法上右鍵選擇“Debug Seleted Tests”即可,和平時(shí)的調(diào)試是一樣的。

如果我們要查看 API 具體返回了什么,可以通過(guò)加斷點(diǎn)調(diào)試來(lái)查看返回結(jié)果的變量字符串值,但這種方式不是最好的選擇。比如對(duì)于同一個(gè) API,我要看看 10 種參數(shù)返回的結(jié)果是什么樣的,每次都通過(guò)斷點(diǎn)調(diào)試來(lái)查看就很麻煩。

除了添加斷點(diǎn)來(lái)調(diào)試,還有一種打印日志的方法來(lái)快速調(diào)試,xUnit 可以很方便地做到這一點(diǎn)。為此我們來(lái)修改一ValuesTests:

public ValuesTests(ITestOutputHelper outputHelper)
{
 var server = new TestServer(WebHost.CreateDefaultBuilder()
  .UseStartup<Startup>());
 Client = server.CreateClient();
 Output = outputHelper;
}

public ITestOutputHelper Output{ get; }

// ... (省略其它代碼)

這里我們?cè)跇?gòu)造函數(shù)中添加了 ITestOutputHelper 參數(shù),xUnit 會(huì)將一個(gè)實(shí)現(xiàn)此接口的實(shí)例注入進(jìn)來(lái)。拿到這個(gè)實(shí)例后,我們就可以用它來(lái)輸出日志了:

[Fact]
public async Task GetById_ShouldBe_Ok()
{
 // Arrange
 var id = 1;

 // Act
 var response = await Client.GetAsync($"/api/values/{id}");

 // Output
 var responseText = await response.Content.ReadAsStringAsync();
 Output.WriteLine(responseText);

 // Assert
 Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}

運(yùn)行(注意不是 Debug)此方法,運(yùn)行結(jié)束后,在“Test Explore”的下方可以可以看到“Output”字樣,點(diǎn)擊它就可以看到輸出的結(jié)果,如圖:

通過(guò)這種方式,每次運(yùn)行測(cè)試我們就可以很方便的查看輸出結(jié)果了。

其它

上面我們是通過(guò)模擬 Http 請(qǐng)求的方式來(lái)調(diào)用 API 測(cè)試的,還有一種就是 new 一個(gè) Controller 來(lái)直接調(diào)用它的 Action 方法來(lái)測(cè)試。比如這樣:

// Arrange
var id = 1;
var controller = new ValuesController();
// Act
var result = controller.Get(id);

如果 Controller 沒(méi)有其它依賴,這種方式當(dāng)然是最方便的。但通常 Controller 是會(huì)有一個(gè)或多個(gè)依賴的,比如這樣:

public class ValuesController : Controller
{
 private readonly ISessionRepository _sessionRepository;

 public ValuesController(ISessionRepository sessionRepository)
 {
  _sessionRepository = sessionRepository;
 }

 // ...
}

我們就要模擬實(shí)例化這個(gè) Controller 的所有依賴,當(dāng)然手動(dòng)模擬是不現(xiàn)實(shí)的,因?yàn)橐粋€(gè)依賴類還可能會(huì)依賴其它的類或接口,依賴鏈可能很長(zhǎng),你不可能每個(gè)依賴都手動(dòng)去實(shí)例化它們。有一個(gè)叫 Moq 的工具可以自動(dòng)來(lái)模擬實(shí)例化依賴,它的用法是這樣的:

// ..
// Arrange
var mockRepo = new Mock<ISessionRepository>();
mockRepo.Setup(...);
var controller = new HomeController(mockRepo.Object);

// Act
var result = await controller.Index();

這種方式我是不推薦的,因?yàn)閽侀_ Moq 的學(xué)習(xí)成本不說(shuō),重要的是它不如模擬 Http 請(qǐng)求那樣接近真實(shí)的調(diào)用場(chǎng)景,所以本文對(duì)它不作過(guò)多的介紹,大家知道有這么回事就行。

到此,相信大家對(duì)“xUnit 如何編寫 ASP.NET Core 單元測(cè)試”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI