[英]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.