如何设置返回IHttpActionResult的模拟?

时间:2016-09-15 20:46:57

标签: c# unit-testing nunit asp.net-web-api2 moq

我使用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()))的返回(1);

我在输出窗口中收到以下内容:

  

'((System.Web.Http.Results.OkNegotiatedContentResult)的ActionResult).Request'   抛出类型' System.InvalidOperationException'

的例外

问题是我告诉Moq期望返回值为1,但Put方法返回OkNegotiatedContentResult

我的问题是(可能是同一个问题):

1)我是否正确设置了Moq并

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 个答案:

答案 0 :(得分:1)

根据您的代码private static Random r = new Random(); public static int[] makeSet(int n, int max) { // The next line guarantees the result is divisible by n int currentMax = n * (1 + r.nextInt(max / n)); Set<Integer> s = new HashSet<Integer>(); // Generate a set of unique values between 0 and the currentMax, // containing those bounds s.add(0); s.add(currentMax); do { s.add(r.nextInt(currentMax)); } while(s.size() <= n); Integer[] values = new Integer[n + 1]; /* * Convert to array, sort the results, and find successive * differences. By construction, those differences WILL sum * to the currentMax, which IS divisible by the number of * values generated by differencing! */ s.toArray(values); Arrays.sort(values); int[] results = new int[n]; for(int i = 0; i < n; ++i) { results[i] = values[i+1] - values[i]; } return results; }

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);response

鉴于测试的断言,您必须更新控制器的null方法,以便在模拟操作之后返回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. 
}