2016-09-15 87 views
1

我使用VisualStudio 2015,.NET 4.6,Moq 4.5.2,Nunit 3.4.1來測試WebApi2控制器。然而,嘲笑預期控制器方法時收到一個響應null對象:如何設置返回IHttpActionResult的模擬?

變種響應=的ActionResult作爲NegotiatedContentResult;

我在猜測我必須設置我的模擬UserService不正確嗎?

我懷疑的是,這部分是罪魁禍首:

userServiceMock.Setup(服務=> service.InsertOrUpdateUser( It.IsAny()))。 退貨(1);

正如我得到的輸出窗口如下:

'((System.Web.Http.Results.OkNegotiatedContentResult)的ActionResult).Request' 扔類型的異常「系統.InvalidOperationException'

問題是我告訴Moq預期返回值爲1,但Put方法返回OkNegotiatedContentResult

我的問題是(可能是相同的問題):

1)我是否正確設置我的起訂量和

2)我怎麼解決這個問題,所以我的反應對象填充?

非常感謝。

下面是測試方法:

[Test] 
public void Put_ShouldUpdate_User() 
{ 
    // Arrange 
    var userServiceMock = new Mock<IUserService>(); 

    userServiceMock.Setup(service => service.InsertOrUpdateUser(
     It.IsAny<User>())).Returns(1); 

    var controller = new UsersController(userServiceMock.Object); 

    // Act 
    IHttpActionResult actionResult = controller.Put(

     new User() 
     { 
      Id = 1, 
      Name = "Joe" 
     }); 

    var response = actionResult as NegotiatedContentResult<User>; 

    // Assert: 
    Assert.IsNotNull(response); 
    var newUser = response.Content; 
    Assert.AreEqual(1, newUser.Id); 
    Assert.AreEqual("Joe", newUser.Name); 
} 

這裏是UserController方法:

// PUT api/users/1 
public IHttpActionResult Put(User user) 
{ 
    if (!ModelState.IsValid) 
    { 
     return BadRequest(ModelState); 
    } 

    return Ok(_userService.InsertOrUpdateUser(user)); 

} 

最後,對於UserService方法:

public int InsertOrUpdateUser(User user) 
{ 
    return _userRepository.InsertOrUpdateUser(user); 
} 
+1

看起來像模擬設置應該沒問題 - 配置的行爲應該像方法一樣返回一個int。我確實注意到你的異常對OkNegotiatedContentResult類型顯示了一個強制類型,但是你的代碼嘗試訪問它作爲NegotiatedContentResult - 它們不共享一個公共基類,這可能是原因嗎? – Andrew

+0

謝謝安德魯。是的,我早些時候發現並嘗試將NegotiatedContentResult更改爲OKNegotiatedContentResult,但它似乎並不重要,所以我只是將它離開了。 –

+0

哪一行是拋出的異常? – Andrew

回答

1

根據你的代碼IUserService

public interface IUserService { 

    int InsertOrUpdateUser(User user); 

} 

返回int

如果你做到以下幾點在你的控制器

return Ok(_userService.InsertOrUpdateUser(user)); 

然後根據界面和您的設置模擬上,將返回的OkNegotiatedContentResult<int>響應類型。但是,在您的測試,你這樣做

var response = actionResult as NegotiatedContentResult<User>; 

,你投你的返回結果作爲NegotiatedContentResult<User>這將導致Assert.IsNotNull(response);失敗作爲演員會導致responsenull

鑑於斷言測試,那麼你就必須更新你的控制器的Put方法,像這樣的嘲笑動作之後返回User user ...

public IHttpActionResult Put(User user) { 
    if (!ModelState.IsValid) { 
     return BadRequest(ModelState); 
    } 
    var count = _userService.InsertOrUpdateUser(user); 
    if(count == 1) 
     return Ok(user); 
    else 
     return BadRequest(); // 500 (Internal Server Error) you choose. 
} 

和如下

也更新測試
//...other code removed for brevity 

var response = actionResult as OkNegotiatedContentResult<User>; 

// Assert: 
Assert.IsNotNull(response); 
var newUser = response.Content; 
Assert.AreEqual(1, newUser.Id); 
Assert.AreEqual("Joe", newUser.Name); 
+1

感謝Nkosi,就是這樣。我的監督很傻,我不想改變控制器,所以我改變了測試 - 本質上測試正確的int返回到我的Assert。 。 –