2016.6.27 微軟已經正式發佈了.NET Core 1.0 RTM,可是工具鏈仍是預覽版,一樣的大量的開源測試庫也都是至少發佈了Alpha測試版支持.NET Core, 這篇文章 The State of .Net Core Testing Today 就將各個開源測試庫的目前進展進行了彙總。本文咱們的目的是在咱們構建咱們應用程序的時候可以進行測試,如何使用XUnit結合你能夠經過爲你的項目添加不一樣的測試用例NSubstitute進行單元測試,同時對整個項目進行集成測試。此次咱們使用Visual Studio 2015 Update 3進行編寫 。xUnit.net是基於.NET Framework 的開源測試工具。經過xUnit.net能夠針對C#/F#/VB.NET等進行單元測試。ASP.NET Core 更直接把以往的Visual Studio Unit Test Framework 說再見了,而直接使用上了xUnit.net,xUnit.net基於NUnit 。從網站或者官網上,你能夠找到很多xUnit的優勢,與NUnit和其餘測試框架相比有一下一些優點
1)爲每一個測試方法產生一個對象實例
2)取消了[SetUp]和[TearDown]
3)取消了[ExpectedException]
4)相似於Aspect的功能
5)減小了自定義屬性(Attribute)的數目
6)採用泛型
7)匿名委託
8)可擴展的斷言
9)可擴展的測試方法
10)可擴展的測試類html
瞭解更多關於xUnit.net能夠參考這裏(點擊打開連接[捨棄Nunit擁抱Xunit])。git
首先咱們相似於.NET Core系列 :3 、使用多個項目 建立一個解決方案testdemo,添加一個類庫項目叫作DotnetCoreLib,Library.cs 也替換爲:github
namespace DotnetCoreLib
{
public class Calculator
{
public int Multi(int x, int y)
{
return x * y;
}
}數據庫
}json
下面咱們要建立一個針對DotnetCoreLib的測試項目,具體建立過程咱們參照文章 https://github.com/dotnet/core-docs/tree/master/samples/core/getting-started/unit-testing-using-dotnet-test ,咱們修改DotnetCoreLibTest 項目的project.json ,增長XUnit相關的nuget包引用,並修改部分配置。api
還有咱們設置Framework節點爲 netcoreapp1.0, 依賴的xunit 和xunit.runner的包服務器
"dependencies": {
"dotnet-test-xunit": "2.2.0-preview2-build1029",
"DotnetCoreLib": {
"version": "1.0.0-*",
"target": "project"
},
"xunit": "2.2.0-beta2-build3300",
"xunit.runner.console": "2.2.0-beta2-build3300"
}網絡
Calculator接下來就開始測試咱們的類庫Calculator, 修改Class1.cs爲CalculatorTest.cs ,app
using DotnetCoreLib;
using Xunit;框架
namespace DotnetCoreLibTest
{
public class CalTest
{
private readonly Calculator calculator;
public CalTest()
{
calculator = new Calculator();
}
[Fact]
public void OneMutiOneIsOne()
{
var result = calculator.Multi(1, 1);
Assert.Equal(1, result);
}
[Theory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public void ReturnValue(int value)
{
var result = calculator.Multi(1,value);
Assert.Equal(result, value);
}
}
}
上面的兩個測試,咱們分別用了2個特性[Fact] 和[Theory], [Fact]屬性表示爲一個方法的單個測試,[Theory]屬性表示執行相同的代碼,可是有不一樣的輸入的參數的測試套件。[InlineData] 屬性可用於指定爲這些輸入值。經過特性[Fact] 和[Theory],xUnit就理解了這是個測試方法,而後運行這個方法。在一個測試方法中,咱們通常遵循包含三步驟的AAA模式:
下面咱們運行dotnet test 就能夠看到結果了。
C:\Users\geffz\Documents\Visual Studio 2015\Projects\TestDemo\DotnetCoreLibTest>dotnet test
Project DotnetCoreLib (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
Project DotnetCoreLibTest (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
xUnit.net .NET CLI test runner (64-bit .NET Core win10-x64)
Discovering: DotnetCoreLibTest
Discovered: DotnetCoreLibTest
Starting: DotnetCoreLibTest
Finished: DotnetCoreLibTest
=== TEST EXECUTION SUMMARY ===
DotnetCoreLibTest Total: 4, Errors: 0, Failed: 0, Skipped: 0, Time: 0.206s
SUMMARY: Total: 1 targets, Passed: 1, Failed: 0.
上面的輸出咱們知道已經執行了4個測試,都經過了,[Face]特性標識表示固定輸入的測試用例,而[Theory]特性標識表示能夠指定多個輸入的測試用例,結合InlineData特性標識使用。在上面的例子裏,總共使用了三次InlineData特性標識,每次設定的值都不一樣,在執行單元測試時,設定的值會被測試框架賦值到對應的測試方法的參數裏。你能夠經過爲你的項目添加不一樣的測試用例,這樣就可讓你的代碼獲得充分測試。
在一個分層結構清晰的項目裏,各層之間依賴於事先約定好的接口。在多人協做開發時,大多數人都只會負責本身的那一部分模塊功能,開發進度一般狀況下也不一致。當某個開發人員須要對本身的模塊進行單元測試而依賴的其餘模塊尚未開發完成時,則須要對依賴的接口經過Mock的方式提供模擬功能,從而達到在不實際依賴其餘模塊的具體功能的狀況下完成本身模塊的單元測試工做。這時咱們一般須要有一個單元測試模擬類庫,一直以來,開發者對 mocking 類庫的語法的簡潔性有強烈的需求,NSubstitute 試圖知足這一需求。簡單明瞭的語法可讓咱們將重心放在測試自己,而不是糾纏在測試替代實例的建立和配置上。NSubstitute 已嘗試將最經常使用的操做需求簡單化、易用化,並支持一些不經常使用的或探索性的功能,與此同時還儘量地將其語法向天然語言靠近。關於NSubstitute的更詳細信息請往 NSubstitute徹底手冊索引。
NSubstitute 已經發布2.0 RC版本支持.NET Core。引入NSubstitute 相關nuget包:
咱們把Calculator 類重構下提取出接口ICalculator:
public interface ICalculator
{
int Multi(int x, int y);
}
咱們可讓NSubstitute來建立類型實例的替代實例,能夠建立諸如 Stub、Mock、Fake、Spy、Test Double 等,但當咱們只是想要一個能有必定程度控制的替代實例時,爲何咱們要困擾於此呢?咱們能夠告訴被建立的替代實例,當方法被調用時返回一個值:
[Fact]
public void Test_GetStarted_ReturnSpecifiedValue()
{
ICalculator calculator = Substitute.For<ICalculator>();
calculator.Multi(1, 2).Returns(2);
int actual = calculator.Multi(1, 2);
Assert.Equal(2, actual);
}
下面咱們運行dotnet test 就能夠看到結果了,增長了上面的2個用例,關於NSubstitute的更詳細信息請往 NSubstitute徹底手冊索引。
上面咱們只是對邏輯進行了單元測試。對於Asp.Net Core項目,還須要模擬在網站部署的狀況下對各個請求入口進行測試。NET Core 可爲快速輕鬆集成測試提供很是棒的支持。
TestServer 類爲 ASP.NET Core 中的集成測試執行大部分繁重操做,Microsoft.AspNetCore.TestHost 包中具備此類。本節內容來自於MSDN雜誌《 ASP.NET Core - 實際的 ASP.NET Core MVC 篩選器》,這些集成測試不須要數據庫或 Internet 鏈接或運行的 Web 服務器。它們如同單元測試同樣快速簡單,但最重要的是,它們容許你在整個請求管道中測試 ASP.NET 應用,而不僅是控制器類中的孤立方法。建議儘量編寫單元測試,並針對沒法單元測試的行爲退回到集成測試,但使用此類高性能方式在 ASP.NET Core 中運行集成測試是很是棒的。
經過在一個工程裏同時模擬了服務端(TestServer)和客戶端(HttpClient)的通訊,從而達到了總體測試WebApi接口的目的,相關的代碼放在https://github.com/ardalis/GettingStartedWithFilters/tree/master/IntegrationTests 。文章對ASP.NET CORE MVC的篩選器進行測試,因爲很難經過編寫單元測試來測試此類場景,可是能夠經過ASP.NET Core 的集成測試來達到相同的目的。
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using Filters101;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
namespace IntegrationTests
{
public class AuthorsControllerTestBase
{
protected HttpClient GetClient()
{
var builder = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseEnvironment("Testing");
var server = new TestServer(builder);
var client = server.CreateClient();
// client always expects json results
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Filters101.Models;
using Newtonsoft.Json;
using Xunit;
namespace IntegrationTests.AuthorsController
{
public class Get : AuthorsControllerTestBase
{
private readonly HttpClient _client;
public Get()
{
_client = base.GetClient();
}
[Theory]
[InlineData("authors")]
[InlineData("authors2")]
public async Task ReturnsListOfAuthors(string controllerName)
{
var response = await _client.GetAsync($"/api/{controllerName}");
response.EnsureSuccessStatusCode();
var stringResponse = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<IEnumerable<Author>>(stringResponse).ToList();
Assert.Equal(2, result.Count());
Assert.Equal(1, result.Count(a => a.FullName == "Steve Smith"));
Assert.Equal(1, result.Count(a => a.FullName == "Neil Gaiman"));
}
}
}
此案例中的客戶端是標準的 System.Net.Http.HttpClient,你可使用它向服務器發出請求,正如同經過網絡同樣。但由於全部請求都在內存中進行,因此測試極其快速可靠。在cmd窗口執行單元測試,查看測試結果