如何设置 returns IHttpActionResult 的模拟?

How do I setup a mock that returns IHttpActionResult?

我正在使用 VisualStudio 2015、.NET 4.6、Moq 4.5.2、Nunit 3.4.1 来测试 WebApi2 控制器。但是,在模拟预期的控制器方法时,我得到了一个 null 响应对象:

var response = actionResult as NegotiatedContentResult;

我猜我一定是错误地设置了 UserService 的模拟?

我怀疑这部分是罪魁祸首:

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

因为我在输出中得到以下内容 window:

'((System.Web.Http.Results.OkNegotiatedContentResult)actionResult).Request' threw an exception of type 'System.InvalidOperationException'

问题是我告诉 Moq 期望 return 值为 1,但是 Put 方法 returns 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);
}

根据你的代码IUserService

public interface IUserService {

    int InsertOrUpdateUser(User user);

}

其中 return 是 int

如果您在控制器中执行以下操作

return Ok(_userService.InsertOrUpdateUser(user));

然后根据界面和您的设置模拟,return 响应类型为 OkNegotiatedContentResult<int>。但是在你的测试中你这样做

var response = actionResult as NegotiatedContentResult<User>;

将 returned 结果转换为 NegotiatedContentResult<User> 这将导致 Assert.IsNotNull(response); 失败,因为转换将导致 response 成为 null

鉴于您的测试断言,那么您必须将控制器的 Put 方法更新为 return 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);