web-dev-qa-db-fra.com

Validation de l'état du modèle dans les tests unitaires

J'écris un test unitaire pour un contrôleur comme celui-ci:

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

le modèle ressemble à:

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

Ensuite, j'ai un test unitaire comme celui-ci:

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

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

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

}

En fait, le ModelState est validé ... ce qui est bizarre pour moi car les deux champs sont obligatoires ... Quelqu'un pourrait-il conseiller?

27
bandreas

La raison pour laquelle l'état du modèle est valide est qu'un nouvel état du modèle est créé lorsque vous créez un nouveau contrôleur. L'API Web ne fait pas la liaison de paramètres pour vous ici, elle n'a donc même pas la possibilité d'ajouter des erreurs d'état du modèle.

Si vous souhaitez conserver cela comme test unitaire, vous devez ajouter vous-même les erreurs d'état du modèle et tester ce qui se passe.

Si vous souhaitez tester que l'état du modèle serait invalide sur une vraie demande, je vous recommande de lire cet article de blog:

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

et essayez de tester sur un serveur en mémoire. Une note mineure pour votre cas serait que vous souhaiterez peut-être utiliser un StringContent au lieu d'un ObjectContent sur la demande pour vous assurer que l'API Web essaie de désérialiser et de lier correctement le corps.

27
Youssef Moussaoui

TL; DR Si vous ne voulez pas lire l'article complet fourni par Youssef et voulez une solution rapide pour faire en sorte que ModelState.IsValid renvoie false. Faites ceci.

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

}

Maintenant, je peux imaginer que CreateAccountController () ressemble à quelque chose comme ça pour le minimum ->

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

J'espère que cela donne une réponse rapide à ceux qui recherchent sur Google :)

20
Andreas

Comme mentionné précédemment, vous avez besoin de tests d'intégration pour valider ModelState. Donc, avec Asp.Net Core, je creuse cette question pour ajouter une solution simple pour intégrer les tests avec Asp.Net Core et la validation de ModelState

Ajoutez le package Microsoft.AspNetCore.TestHost et vous pouvez soumettre des demandes de cette manière:

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

Vous pouvez en savoir plus ici: http://asp.net-hacker.rocks/2017/09/27/testing-aspnetcore.html

J'espère que ça aide.

10
Bruno Avelar

J'ai utilisé ce qui suit pour valider l'état du modèle dans le test unitaire Visual studio 2017, C #, 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");
        }

L'exemple concerne une requête au format JSON. Remplacez YourController par le nom de votre contrôleur et YourRequesType par le type d'objet de votre demande.

Cela vous donne la possibilité de tester votre modèle pour validation sans passer par le service.

0
freedeveloper