2016-06-28 84 views
2

我對使用Moq和Nunit進行單元測試還很陌生,而且我遇到了一種情況。我想要的是我的模擬器有一個輸出參數,我的系統正在測試,然後用它來決定採取什麼動作。Moq out參數

我的被測系統是一個MVC API控制器,特別是我試圖測試POST方法。我想在驗證失敗時返回對象的錯誤消息。

這裏是控制器的方法代碼:

 public IHttpActionResult Post(Candidate candidate) 
    { 
     try 
     { 
      if(candidate==null) 
       return BadRequest(); 

      IEnumerable<string> errors; 
      _candidateManager.InsertCandidate(candidate, out errors); 

      if (errors!=null && errors.Any()) 
       return BadRequest(CreateErrorMessage("Invalid candidate: ", errors)); 

      return CreatedAtRoute("DefaultApi", new {id = candidate.CandidateId}, candidate); 

     } 
     catch (Exception) 
     { 
      return InternalServerError(); 
     } 
    } 

這是我的單元測試代碼:

 [Test] 
    [Category("CandidateManagerController Unit Tests")] 
    public void Should_Return_Bad_Request_When_Creating_Invalid_Candidate() 
    { 
     IEnumerable<string> errors = new List<string>() {"error1", "error2"}; 

     var mockManager = new Mock<ICandidateManager>(); 
     mockManager.Setup(x => x.InsertCandidate(new Candidate(), out errors)).Callback(()=>GetErrors(errors)); 

     var sut = new CandidateManagerController(mockManager.Object); 

     var actionResult = sut.Post(new Candidate()); 

     Assert.IsInstanceOf<BadRequestResult>(actionResult); 

    } 

我想到的是,當_candidateManager.InsertCandidate()運行,則錯誤變量被填充。但是,發生什麼情況是,當您逐步執行控制器代碼時,_candidateManager.InsertCandidate()方法運行後,錯誤爲空。

如果任何人有任何想法我做錯了什麼,或者如果我想要做的是不可能使用Moq那麼請讓我知道。

感謝

+0

您必須設置錯誤。什麼是GetErrors的實現? –

回答

0

你必須確保當你調用您使用傳遞給out參數相同的情況下你的SUT否則呼叫將失敗。

在您的示例中,被測方法將空實例傳遞給模擬方法,從而否定測試的設置。

但是,如果您無法爲out提供相同的實例,那麼看起來您無法成功通過模擬。看看Quick Start for Moq瞭解它的功能。

+0

嗨,感謝迄今的迴應。道歉,設置模擬的代碼應該是'var mockManager = new Mock (); mockManager.Setup(x => x.InsertCandidate(new Candidate(),out errors));'當我在actionResult行上放置一個斷點時,我可以看到錯誤包含了我期望的兩個項目,但是當您步入控制器在調用方法時編寫錯誤IEnumerable未設置。讀MOQ快速啓動看起來像我已經設置了相同。我不確定的是,我想要做的事實際上是否可能。 – kcis8rm

1

你想要做什麼是可能的。如果你看看https://github.com/Moq/moq4/wiki/Quickstart上的Quickstart文檔,有一個部分可以展示如何使用out參數來設置方法。我已經對您的代碼進行了兩次更正,並且它可以正常工作。

  1. 您必須爲模擬設置和鍛鍊時使用相同的候選實例。否則,Moq認爲這兩個對象是不同的,你的測試設置變得毫無用處。
  2. 您不必使用回調來設置由模擬的CandidateManager返回的錯誤。 以下是您的測試方法和我的更改。

    [Test] 
    [Category("CandidateManagerController Unit Tests")] 
    public void Should_Return_Bad_Request_When_Creating_Invalid_Candidate() 
    { 
    IEnumerable<string> errors = new List<string>() {"error1", "error2"}; 
    
    //instance to be used for both setup and test later 
    var candidate = new Candidate(); 
    
    var mockManager = new Mock<ICandidateManager>(); 
    
    //removed Callback 
    mockManager.Setup(x => x.InsertCandidate(candidate, out errors)); 
    
    var sut = new CandidateManagerController(mockManager.Object); 
    
    var actionResult = sut.Post(candidate); 
    
    Assert.IsInstanceOf<BadRequestResult>(actionResult); 
    
    }