2016-09-15 2 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' бросил исключение типа «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

похоже, что макет настройки должен быть в порядке - настроенное поведение должно возвращать 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); на неудачу, поскольку бросок приведет к 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. 
} 

, а также обновить тест следующего

//...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. Еще раз спасибо за ясность , –