2

我使用commonlibrary(http://commonlibrarynet.codeplex.com/)的驗證碼類。我的代碼工作和一切,但現在我試圖編寫單元測試。FakeItEasy和FluentValidation從commonlibnet僞造的驗證碼

我的驗證規則是:

RuleFor(x => x.CaptchaUserInput) 
      .NotEmpty() 
      .Must((x, captchaUserInput) => Captcha.IsCorrect(captchaUserInput, x.CaptchaGeneratedText)) 
      .WithMessage("Invalid captcha code"); 

在我設立的代碼我試圖做到以下幾點:

A.CallTo(() => Captcha.IsCorrect()).Returns(true); 

,但我得到了以下錯誤消息:

SetUp : FakeItEasy.Configuration.FakeConfigurationException : 

The current proxy generator can not intercept the specified method for the following reason: 
- Static methods can not be intercepted. 


at FakeItEasy.Configuration.DefaultInterceptionAsserter.AssertThatMethodCanBeInterceptedOnInstance(Metho dInfo method, Object callTarget) 
at FakeItEasy.Configuration.FakeConfigurationManager.CallTo(Expression`1 callSpecification) 
at ProdMaster.Hosts.Web.Tests.Unit.Controllers.AccountControllerTests.SetUp() in  AccountControllerTests.cs: line 44 

所以真正的問題是如何使用FakeItEasy僞造靜態方法。

TIA,

大衛

回答

7

有沒有辦法攔截靜態方法FakeItEasy(在沒有其他,目前開源,.net的免費模擬框架)。爲了能夠模擬靜態(和密封類),你必須從Telerik購買Typemock Isolator或Just Mock。

許多開發人員認爲靜態是代碼異味(在大多數情況下)。因此,開源嘲諷框架不支持這一事實被認爲是一件好事,因爲它促進了更好的設計。嘲笑的「黃金法則」是「如果你不能控制它,不要嘲笑它」,所以解決你遇到的問題的常見方式是創建一個圍繞靜態調用的包裝。你測試與這個 - mockable-wrapper的交互。 System.DateTime.Now是您經常希望在測試中測試的靜態示例。爲了隔離這個你的測試,你會做這樣的事情:

public interface ISystemTimeProvider 
{ 
    DateTime Now { get; } 
} 

public class DateTimeNowSystemTimeProvider 
    : ISystemTimeProvider 
{ 
    public DateTime Now 
    { 
     get 
     { 
      return DateTime.Now; 
     } 
    } 
} 

通過以上接口和實現你的SUT將取決於(通過構造函數注入爲例)的接口。在你的測試中,你會注入一個假的(A.Fake<ISystemTimeProvider>())。 DateTimeSystemTimeProvider的實現永遠不會被單元測試,它的級別非常低,除了集成測試外,不需要任何測試。

我不是很熟悉你正在談論的captcha庫,所以我不確定你在這種情況下如何應用上述模式,但我確信它可以這樣或那樣完成。

+0

謝謝你在這裏和通過電子郵件的答案。非常感謝。我並沒有試圖嘲笑Captcha控制,而是扼殺了它。從Roy Osherove關於單元測試的書中我已經閱讀和理解的內容可以看出,這是我應該做的,因爲它是一種外部依賴性,不應該使我的測試失敗。無論如何,我相信我已經理解了你的觀點,並且會嘗試調整提供給Captcha控件的代碼。再次感謝你。大衛 – DavidS 2011-04-24 12:10:34

1

與Patrik的解決方案類似,您可以將委託傳遞到調用此靜態方法的類的構造函數中。

所以你會在默認構造函數中設置一個指向Captcha.IsCorrect的委託。

此委託變量將在您的fluentValidation代碼中調用。單元測試時,您將創建一個新的構造函數,您將在其中將代理設置爲指向您的模擬方法。 (在你的情況下,只是返回true)

public class SomeValidator 
{ 
    Func<string, string, bool> _captchaVerifier; 

    public SomeValidator() 
    { 
     _captchaVerifier = Captcha.IsCorrect; 
    } 

    public SomeValidator(Func<string, string, bool> method) 
    { 
     _captchaVerifier = method; 
    } 

    public void Validate() 
    { /* your code */ 
     RuleFor(x => x.CaptchaUserInput) 
     .NotEmpty() 
     .Must((x, captchaUserInput) => _captchaVerifier(captchaUserInput, x.CaptchaGeneratedText)) 
     .WithMessage("Invalid captcha code"); 
    } 
}