Подтвердить что ты не робот

Проверка состояния модели в модульных тестах

Я пишу unit test для такого контроллера:

public HttpResponseMessage PostLogin(LoginModel model)
{
    if (!ModelState.IsValid)
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
}

модель выглядит следующим образом:

public class LoginModel
{
    [Required]
    public string Username { set; get; }
    [Required]
    public string Password { set; get; }
}

Тогда у меня есть unit test, как этот:

[TestMethod]
public void TestLogin_InvalidModel()
{
    AccountController controller = CreateAccountController();

    ...
    var response = controller.PostLogin(new LoginModel() {  });

    Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);

}

На самом деле ModelState проверяется... что странно для меня, поскольку оба поля необходимы... Может ли кто-нибудь посоветовать?

4b9b3361

Ответ 1

Причина, по которой состояние модели действительна, заключается в том, что при новом обновлении контроллера создается новое состояние модели. Web API не выполняет привязки параметров для вас здесь, поэтому у него даже нет возможности добавлять ошибки состояния модели.

Если вы хотите сохранить это как unit test, тогда вы должны сами добавить ошибки состояния модели и проверить, что происходит.

Если вы хотите проверить, что состояние модели недействительно в реальном запросе, я рекомендую вам прочитать это сообщение в блоге:

http://blogs.msdn.com/b/youssefm/archive/2013/01/28/writing-tests-for-an-asp-net-webapi-service.aspx

и попробуйте протестировать сервер с памятью. Одна из незначительных замечаний для вашего случая заключалась бы в том, что вы можете использовать StringContent вместо ObjectContent в запросе, чтобы убедиться, что веб-API пытается десериализовать и правильно привязать тело.

Ответ 2

TL; DR Если вы не хотите читать всю статью, предоставленную Youssef, и хотите быстро решить, как заставить ModelState.IsValid вернуть false. Сделай это.

[TestMethod]
public void TestLogin_InvalidModel()
{
    AccountController controller = CreateAccountController();
    // new code added -->
    controller.ModelState.AddModelError("fakeError", "fakeError");
    // end of new code
    ...
    var response = controller.PostLogin(new LoginModel() {  });

    Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);

}

Теперь я могу представить, что CreateAccountController() выглядит примерно так: минимум →

return new AccountApiController()
{
    Request = new HttpRequestMessage(),
    Configuration = new HttpConfiguration()
};

Надеюсь, что это даст быстрый ответ для этих поисковых запросов:)

Ответ 3

Как упоминалось ранее, вам нужны интеграционные тесты для проверки ModelState. Итак, с Asp.Net Core я решил этот вопрос, чтобы добавить простое решение для интеграции тестов с Asp.Net Core и проверки ModelState

Добавьте пакет Microsoft.AspNetCore.TestHost, и вы сможете отправлять запросы так просто:

var server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
var client = server.CreateClient();
var model = new { Name = String.Empty };
var content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
var result = await client.PostAsync("/api/yourApiEndpoint", content);
result.StatusCode.Should().Be(HttpStatusCode.BadRequest);

Вы можете найти больше об этом здесь: http://asp.net-hacker.rocks/2017/09/27/testing-aspnetcore.html

Надеюсь, это поможет.

Ответ 4

Я использовал следующее для проверки состояния модели в модульном тесте Visual studio 2017, С#, NET 4.x.x

   [TestMethod]
        public void TestYourValidationModel()
        {
            var configuration = new HttpConfiguration();
            configuration.Filters.Add(new ValidateModelAttribute());
            // Get the quote
            var controller = new YourController
            {
                Request = new HttpRequestMessage(),
                Configuration = configuration
            };
            var request = YourRequestObject;
            controller.Request.Content = new ObjectContent<YourRequestType>(
                request, new JsonMediaTypeFormatter(), "application/json");
            controller.Validate(request);
            Assert.IsTrue(controller.ModelState.IsValid, "This must be valid");
        }

Пример для запроса в формате JSON. Замените YourController на имя вашего контроллера, а YourRequesType на тип объекта вашего запроса.

Это дает вам возможность протестировать вашу модель для проверки без обращения в сервис.