2015-01-17 45 views
4

我最近開始學習如何編寫單元測試,以及測試哪些功能部件以及如何模擬功能。我使用NSubstitute作爲我的嘲笑框架。我的例子基本上調用一個回購類,然後使一個WEB API Web調用到外部服務,即:AddCreditCard,然後返回結果。我爲AddCreditCard創建了2個單元測試,一個用於成功,另一個用於Fail。我仍然不是100%確定我正在做所有這些。單元測試通過,但我不知道我的斷言是否在正確的數據上完成...歡迎所有幫助和建議!我正在寫我的單元測試嗎? NUnit + NSubstitute

public interface IApiResponse<T> 
{ 
    HttpStatusCode StatusCode { get; set; } 
    T Result { get; set; } 
    string ErrorMessage { get; } 
    bool HasErrors { get; } 
} 

public interface ISignedRequest 
{ 
    void ConfigureSettings(SignedRequestSettings settings); 

    IApiResponse Post(string jsonData, Dictionary<string, string> parameters = null, 
     IOptionalHeaders optionalHeaders = null); 
} 


public class PaymentRepository 
{ 
    private readonly SignedRequestSettings _settings; 
    private readonly ISignedRequest _signedRequest; 

    public PaymentRepository(ISignedRequest signedRequest = null) 
    { 
     if (signedRequest == null) 
      _signedRequest = new SignedRequest(); 
     else 
      _signedRequest = signedRequest; 
    } 

    public IApiResponse AddCreditCard(CreditCard request) 
    { 
     var jsonData = 
      JsonConvert.SerializeObject(request); 

     string action = string.Format("customers/{0}/paymentmethods", request.ConnectId); 
     _settings.Url = string.Format("{0}{1}", String.Empty, action); 
     _signedRequest.ConfigureSettings(_settings); 

     return _signedRequest.Post(jsonData); 
    } 
} 

    [Test] 
    public void AddCreditCard_GivenValidCreditCard_ReturnsCreatedResult() 
    { 
     //Given 
     var apiResponse = Substitute.For<IApiResponse>(); 
     apiResponse.StatusCode = HttpStatusCode.Created; 

     var signedRequest = Substitute.For<ISignedRequest>(); 
     signedRequest.Post(Arg.Any<String>()).Returns(apiResponse); 

     var creditCard = Substitute.For<CreditCard>(); 
     creditCard.ConnectId = Guid.Parse("1fc1ad83-cd4e-4b68-bce6-e03ee8f47fb6"); 

     var repo = new PaymentRepository(signedRequest); 

     //When 
     var addCreditCardResponse = repo.AddCreditCard(creditCard); 

     //Then 
     signedRequest.Received(1).ConfigureSettings(Arg.Any<SignedRequestSettings>()); 
     signedRequest.Received(1).Post(Arg.Any<String>()); 

     Assert.AreEqual(HttpStatusCode.Created, addCreditCardResponse.StatusCode); 
    } 

[Test] 
    public void AddCreditCard_GivenInvalidCreditCard_ReturnsHasErrorsResult() 
    { 
     //Given 
     var apiResponse = Substitute.For<IApiResponse>(); 
     apiResponse.HasErrors.Returns(true); 
     apiResponse.ErrorMessage.Returns("Add credit card error message"); 

     var signedRequest = Substitute.For<ISignedRequest>(); 
     signedRequest.Post(Arg.Any<String>()).Returns(apiResponse); 

     var creditCard = Substitute.For<CreditCard>(); 
     creditCard.ConnectId = Guid.Parse("1fc1ad83-cd4e-4b68-bce6-e03ee8f47fb6"); 

     var repo = new PaymentRepository(signedRequest); 

     //When 
     var addCreditCardResponse = repo.AddCreditCard(creditCard); 

     //Then 
     signedRequest.Received(1).ConfigureSettings(Arg.Any<SignedRequestSettings>()); 
     signedRequest.Received(1).Post(Arg.Any<String>()); 

     Assert.AreEqual(apiResponse.HasErrors, addCreditCardResponse.HasErrors); 
     Assert.AreEqual(apiResponse.ErrorMessage, addCreditCardResponse.ErrorMessage); 
    } 
+0

第一次腮紅,這些看起來像很棒的單元測試。我的一個建議是在'signedRequest.Received(1)'調用中使用特定參數或[參數匹配器](http://nsubstitute.github.io/help/argument-matchers/)。除非這些值對你正在測試的東西不重要。 –

回答

2

我認爲你的測試大多數都可以,但是有一些問題。無論你的測試有這些線在底部:

signedRequest.Received(1).ConfigureSettings(Arg.Any<SignedRequestSettings>()); 
signedRequest.Received(1).Post(Arg.Any<String>()); 

難道這些測試的真正重要的是這些方法被調用你的signedRequest替代品?我建議它可能不是。如果這些電話沒有提出,我會認爲你的測試會失敗(雖然這在某種程度上是一個文體決定)。

我要說的第二件事是你缺少一個或多個測試(再次,這個數字有點風格)。現在,您並未驗證signedRequest替代品上提供給ConfigureSettingsPost調用的信息。你的存儲庫代碼可能只是做_signedRequest.Post("some random string");,你的測試仍然會通過。我會添加另一個驗證這些調用的測試,以確保請求實際上已正確發送。這是驗證有意義的地方。例如:

signedRequest.Received(1).ConfigureSettings(Arg.Is<SignedRequestSettings>(x=>x.Url == someHardCodedUrl)); 
signedRequest.Received(1).Post(someHardCodedJsonString); 
相關問題