簡體   English   中英

如何測試隱藏測試數據的服務方法

[英]How to test a service method that hides the test data

試想一下,我的asp.net mvc Controller方法可能具有以下代碼:

testplanService.AddTestplan(testplan,template,release);

它調用以下實現的服務方法:

public TestplanService
{

public void AddTestplan(Testplan testplan, Template template, Release release)
        {
           testplan.CreatedAt = DateTime.Now;
           testplan.UserId = WindowsIdentity.GetCurrent().Name;
           testplan.Name = release.Name + " " + template.Name + " " + testplan.UserId + " " + testplan.CreatedAt;

           _provider.AddTestplan(testplan, template, release);                             
        }

}

當我不知道此方法中的值時,如何在ASSERT中測試CreatedAt,UserId和Name屬性?

是的,我知道我可以將testplan對象中的所有3個值都傳遞給服務方法,但是mvc中的Controller類不應具有這3行邏輯。

那你會怎么做?

試想一下,我的asp.net mvc Controller方法可能具有以下代碼:

testplanService.AddTestplan(testplan,template,release);

我不想想象這樣的事情。 正確的方法是您的控制器使用抽象,而不是實際的實現。 因此,您不依賴於實際的服務實現,而是在控制器中使用的這個testplanService變量將是一個簡單的接口或一個抽象類,它將被注入到控制器的構造函數中。

現在,在單元測試中,您實際上可以模擬此接口並單獨測試控制器。

現在讓我們考慮該服務的實際實現:

public void AddTestplan(Testplan testplan, Template template, Release release)
{
    testplan.CreatedAt = DateTime.Now;
    testplan.UserId = WindowsIdentity.GetCurrent().Name;
    testplan.Name = release.Name + " " + template.Name + " " + testplan.UserId + " " + testplan.CreatedAt;
    _provider.AddTestplan(testplan, template, release);                             
}

此方法存在兩個問題。 首先,它取決於不確定的數據,例如DateTime.Now ,這些數據很難進行單元測試。 馬丁·福勒(Martin Fowler)在單元測試中有一篇關於非確定性的文章 它還取決於當前的WindowsIdentity 所有這些都很難進行單元測試,因為您的方法依賴於實際的實現而不是抽象。

因此,您將必須抽象出可以在單元測試中模擬的提供程序背后的那些概念。 確保所有組件之間均弱耦合。 您會發現與他們孤立地工作要容易得多。


更新:

根據評論部分的要求,以下是如何抽象日期時間檢索的示例:

考慮以下類別:

public class WeekendTester
{
    public bool IsWeekendSoon()
    {
        return (int)DateTime.Now.DayOfWeek > 3;
    }
}

顯然,單元測試IsWeekendSoon非常困難,因為這取決於單元測試的運行日期。

因此,為了打破這種方法的不確定性,您可以執行以下操作:

public class WeekendTester
{
    private readonly Func<DateTime> _dateTimeProvider;
    public WeekendTester(Func<DateTime> dateTimeProvider)
    {
        _dateTimeProvider = dateTimeProvider;
    }

    public bool IsWeekendSoon()
    {
        return (int)_dateTimeProvider().DayOfWeek > 3;
    }
}

現在您只需要配置自己喜歡的DI框架以將() => DateTime.Now注入到該對象的構造函數中,並在單元測試中輕松模擬它即可:

[TestMethod]
public void Weekend_Is_Still_Far_Away_From_The_28_th_Of_February_2012()
{
    // arrange
    Func<DateTime> providerMock = () => new DateTime(2012, 2, 28);
    var sut = new WeekendTester(providerMock);

    // act
    var actual = sut.IsWeekendSoon();

    // assert
    Assert.IsFalse(actual);
}

您可以看到在此示例中,我們如何能夠在單元測試中以所需的任何日期強制該方法工作,以驗證該方法的正確行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM