.NET Core系列 :4 測試

来源:http://www.cnblogs.com/shanyou/archive/2016/08/15/5770840.html
-Advertisement-
Play Games

2016.6.27 微軟已經正式發佈了.NET Core 1.0 RTM,但是工具鏈還是預覽版,同樣的大量的開源測試庫也都是至少發佈了Alpha測試版支持.NET Core, 這篇文章 The State of .Net Core Testing Today 就將各個開源測試庫的目前進展進行了彙總。 ...


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)可擴展的測試類

         瞭解更多關於xUnit.net可以參考這裡(點擊打開鏈接[捨棄Nunit擁抱Xunit])。

 

使用xUnit.net 單元測試

 

 

 

首先我們類似於.NET Core系列 :3 、使用多個項目 創建一個解決方案testdemo,添加一個類庫項目叫做DotnetCoreLib,Library.cs 也替換為:

namespace DotnetCoreLib
{
    public class Calculator
    {
        public int Multi(int x, int y)
        {
            return x * y;
        }
    }

}

image

下麵我們要創建一個針對DotnetCoreLib的測試項目,具體創建過程我們參照文章 https://github.com/dotnet/core-docs/tree/master/samples/core/getting-started/unit-testing-using-dotnet-test ,我們修改DotnetCoreLibTest 項目的project.json ,增加XUnit相關的nuget包引用,並修改部分配置。

 

image 

還有我們設置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 ,

 

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模式:

  1. Arrange:為測試準備
  2. Act:運行SUT(實際測試的代碼)
  3. Assert:校驗結果

下麵我們運行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特性標識,每次設定的值都不同,在執行單元測試時,設定的值會被測試框架賦值到對應的測試方法的參數里。你可以通過為你的項目添加不同的測試用例,這樣就可以讓你的代碼得到充分測試。

 

xUnit.net 搭配NSubstitute 進行單元測試

 

   在一個分層結構清晰的項目里,各層之間依賴於事先約定好的介面。在多人協作開發時,大多數人都只會負責自己的那一部分模塊功能,開發進度通常情況下也不一致。當某個開發人員需要對自己的模塊進行單元測試而依賴的其他模塊還沒有開發完成時,則需要對依賴的介面通過Mock的方式提供模擬功能,從而達到在不實際依賴其他模塊的具體功能的情況下完成自己模塊的單元測試工作。這時我們通常需要有一個單元測試模擬類庫,一直以來,開發者對 mocking 類庫的語法的簡潔性有強烈的需求,NSubstitute 試圖滿足這一需求。簡單明瞭的語法可以讓我們將重心放在測試本身,而不是糾纏在測試替代實例的創建和配置上。NSubstitute 已嘗試將最常用的操作需求簡單化、易用化,並支持一些不常用的或探索性的功能,與此同時還儘可能地將其語法向自然語言靠近。關於NSubstitute的更詳細信息請往 NSubstitute完全手冊索引

 

NSubstitute 已經發佈2.0 RC版本支持.NET Core。引入NSubstitute 相關nuget包:

image

我們把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完全手冊索引

image

 

集成測試

上面我們只是對邏輯進行了單元測試。對於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視窗執行單元測試,查看測試結果

image


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 問題 一般Android手機用usb數據線連接到windows操作系統的電腦上後,會自動將手機存儲卡以移動存儲的方式顯示在電腦里. 但是如果操作系統是Mac的,就沒有這個存儲設備.問題來了,Mac電腦如何讀取手機上的文件呢? 解決方式 從Android的網站下載一個傳輸工具,地址是, 安裝打開後,會 ...
  • 比如 ssh 10.0.1.23,出現以下情況: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @@@@@@@@@@@@@@@ ...
  • 版權聲明:本文為MULTIBEANS ORG研發跟隨文章,未經MLT ORG允許不得轉載。 最近做項目,需要開發安卓應用,實現串口的收發,目測CH340G在安卓手機上非常麻煩,而且驅動都是Java版本的, 就沒選擇,博主在大二的時候學習過Java SE基本的語法,寫過一些小程式就放棄了Java的道路 ...
  • 最近在做項目中用到2013中的ReportView11 在本機IIS中使用完全沒問題 但是放到伺服器上總是出問題 解決辦法:(1)首先在自己機器上開發的時候 是不用引用 Microsoft.ReportViewer.Common.dll和Microsoft.ReportViewer.WebForms ...
  • C# 軟體配置方法。通常情況下我們使用appSetting來進行配置,通過 Glacier 可以使用嵌入的 HOCON 或獨立的 HOCON 配置文件配置,同時支持類型綁定功能,方便統一管理軟體配置。 ...
  • 最近閑來無事給自己寫了家庭財務收支管理系統,也就包含支出管理,收入管理和一些統計功能。 先說登錄模塊,因為涉及GET和POST請求,這些東西都是能被監控和抓取的所以就考慮這使用RSA加密解密方式傳輸用戶名和密碼參數,頁面JS如下: 1 /*需要引入三個JS文件,BigInt.js、RSA.js和Ba ...
  • 靜態 1、普通成員普通成員都是屬於對象的用對象調用 2、靜態成員靜態成員是屬於類的用類名調用 class FenBi{public int length;//普通成員public string color;//} static 靜態關鍵字 靜態方法裡面不能包含普通成員 普通方法裡面可以包含靜態成員 ...
  • 我們先思考幾個問題: 接下來,先開始我們的正文。 自己實現迭代器 .net中迭代器是通過IEnumerable和IEnumerator介面來實現的,今天我們也來依葫蘆畫瓢。 首先來看看這兩個介面的定義: 並沒有想象的那麼複雜。其中IEnumerable只有一個返回IEnumerator的GetEnu ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...