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

Я пишу модульный тест для контроллера следующим образом:

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; }
}

Затем у меня есть модульный тест, подобный этому:

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

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

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

}

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


person bandreas    schedule 27.06.2013    source источник
comment
Для aspnetcore см. stackoverflow.com/ вопросы/43229338/   -  person Michael Freidgeim    schedule 02.05.2018


Ответы (5)


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

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

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

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

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

person Youssef Moussaoui    schedule 27.06.2013
comment
+1 с Юссефом. Кроме того, вы можете взглянуть на следующий постер веб-API для конвейера запросов. asp.net/posters/web- api/ASP.NET-Web-API-Poster-grayscale.pdf - person Kiran Challa; 27.06.2013

TL; DR Если вы не хотите читать всю статью, предоставленную Юссефом, и хотите быстро решить, как заставить 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()
};

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

person Andreas    schedule 12.06.2015
comment
Спасибо за пример. Единственное отличие, которое я сделал, это тип утверждения: Assert.IsInstanceOfType(actResult, typeof(InvalidModelStateResult)); - person Mateusz Migała; 17.01.2017

Как упоминалось ранее, вам нужны интеграционные тесты для проверки 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

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

person Bruno Avelar    schedule 13.10.2017
comment
Правильный ответ, если вы ищете основной ответ .net. - person THBBFT; 24.11.2017

Я использовал следующее для проверки состояния модели в модульном тесте 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 на тип объекта вашего запроса.

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

person freedeveloper    schedule 29.08.2019

Мне не удалось получить свойство response.StatusCode для объекта ответа. Поэтому мне пришлось утверждать, как показано ниже, что хорошо для меня.

IHttpActionResult actionResult = контроллер.ActionMethod(запрос);

Assert.IsInstanceOf (результат действия);

Есть ли способ проверить код состояния на объекте ответа? Как например. Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);

person Maverick Calibre    schedule 08.05.2021