.NET單元測試(五):多線程

鑒于.NET Framework 4.5后.NET增加了對 async/await 的支持,本文討論的異步內(nèi)容均基于async/await

??客戶端界面開發(fā),多線程是逃不了的話題,而多線程的加入勢必對程序的穩(wěn)定性帶來挑戰(zhàn),單元測試就顯得更為重要。相對于同步代碼的測試,多線程單元測試有更多細(xì)節(jié)需要注意。

async void 和 async Task。

??假設(shè)某一天你運氣不好,需要為類似如下的方法補充單元測試:

public static bool Changed;

public static async void ChangeAsync()
{
    await Task.Run(() =>
    {
        Task.Delay(1000);
        Changed = true;
    });
}

你發(fā)現(xiàn),要測試此方法需要用一些奇葩的方式,比如:

[TestMethod()]
public void ChangeAsyncTest_OriginalFalse_ChangeToTrue()
{
    AsyncClient.Changed = false;

    AsyncClient.ChangeAsync();
    Thread.Sleep(1100);

    Assert.IsTrue(AsyncClient.Changed);
}

顯然,這種延時等待是極其惡心的,如果ChangeAsync方法返回的不是void而是Task,我們就可以愉快的await了:

[TestMethod()]
public async Task ChangeAsyncTest_OriginalFalse_ChangeToTrue()
{
    AsyncClient.Changed = false;

    await AsyncClient.ChangeAsync();

    Assert.IsTrue(AsyncClient.Changed);
}

需要特別注意的是,在異步單元測試方法中也必須返回Task,這是MSTest的約定,否則這個測試方法無法運行起來。(實際上MSTest也需要使用返回的Task來收集異常,關(guān)于這部分更多內(nèi)容可以參見Async/Await最佳實踐

拋棄ExpectedException

??在測試程序是否按照預(yù)期的拋出了異常,我們常常會用ExpectedException,這家伙有一個問題,它是對整個測試方法的方法體做捕獲,也就是說測試方法中的非action代碼拋出了異常依然能夠被ExpectedException捕獲,這就造成潛在的bug,為了解決此問題,在MSTest V2之前往往需要寫一些輔助方法,但MSTest V2斷言庫中增加了Assert.ThrowsExceptionAsync和Assert.ThrowsException,可以精確的定位在哪段代碼中拋出了異常。假設(shè)我們的被測代碼跟下面類似:

public static async Task ChangeAsync()
{
    await Task.Run(() =>
    {
        throw new InvalidOperationException();
    });
}

測試代碼可以這樣寫:

[TestMethod()]
public async Task ChangeAsyncTest_ThrowInvalidOperationException()
{
    await Assert.ThrowsExceptionAsync<InvalidOperationException>(async () =>
    {
        await AsyncClient.ChangeAsync();
    });
}

異步方法mock

??在moq中,異步方法的mock也是極其簡單的,假設(shè)有這樣的接口:

public interface ITextReader
{
    Task<string> ReadTextAsync();
}

測試代碼中mock其返回結(jié)果可以有如下兩種寫法:

var mockTextReader = new Mock<ITextReader>();

//可以這樣
mockTextReader.Setup(x => x.ReadTextAsync()).Returns(async ()=>await Task.FromResult("mockValue"));

//也可以這樣
mockTextReader.Setup(x => x.ReadTextAsync()).ReturnsAsync(()=> "mockValue");



2017-11-30 15:26:34

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 在之前的系列博客中,主要圍繞的是測試工具的介紹與使用。經(jīng)過幾個月的沉寂,在項目中摸索與實踐單元測試,曾經(jīng)踩坑...
    水木飛雪閱讀 2,961評論 0 8
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,711評論 19 139
  • 什么是單元測試 在計算機編程中,單元測試(Unit Testing)又稱為模塊測試, 是針對程序模塊(軟件設(shè)計的最...
    HelloCsl閱讀 11,108評論 1 46
  • 本文主要介紹了在 C# 中使用 Async 和 Await 關(guān)鍵字進(jìn)行異步編程的心得,是入門級的學(xué)習(xí)筆記。 題解:...
    BossOx閱讀 5,952評論 4 27
  • 除去所有浪漫的驚喜和冗雜的情話,也許愛情只是一段盡可能長久的陪伴,長到四季穿過蒹葭,長到青絲抽離成...
    末歡閱讀 1,253評論 0 3

友情鏈接更多精彩內(nèi)容