18

sto scrivendo un test di unità per un controller come questo:Modello convalida dello stato in unità di test

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

il modello si presenta come:

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

Poi devo unit test come questo:

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

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

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

} 

in realtà il ModelState viene convalidato ... che è strano per me come sono necessari entrambi i campi ... Could qualcuno lo consiglia?

risposta

23

Il motivo per cui lo stato del modello è valido è che quando si avvia un controller viene creato un nuovo stato del modello. L'API Web non sta eseguendo il collegamento dei parametri qui, quindi non ha nemmeno la possibilità di aggiungere errori di stato del modello.

Se si desidera mantenere questo come un test di unità, è necessario aggiungere gli errori di stato del modello e verificare ciò che accade.

Se si desidera verificare che lo stato modello sarebbe invalido su una richiesta vera e propria, vi consiglio di leggere questo post del blog:

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

e cerco di test su un server in-memory. Una nota secondaria per il tuo caso potrebbe essere che potresti voler utilizzare un oggetto StringContent anziché un oggetto ObjectContent sulla richiesta per assicurarti che l'API Web tenti di deserializzare e associare correttamente il corpo.

+2

+1 con Youssef. Inoltre, puoi dare un'occhiata al seguente poster API Web per la pipeline della richiesta. http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster-grayscale.pdf –

16

TL; DR Se non si desidera leggere l'intero articolo fornito da Youssef e si desidera una soluzione rapida su come rendere ModelState.IsValid restituito falso. Fai questo.

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

} 

Ora posso immaginare la CreateAccountController() sembra qualcosa di simile per minimo ->

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

Spero che questo dà una risposta rapida per coloro googling :)

+0

Grazie per l'esempio. L'unica differenza che ho fatto è stata il tipo di assert: Assert.IsInstanceOfType (actResult, typeof (InvalidModelStateResult)); –

1

Come accennato prima, è bisogno di test di integrazione per convalidare ModelState. Così, con Asp.Net Core Sto scavando questa domanda per aggiungere una soluzione semplice per l'integrazione di test con Asp.Net core e validazione di ModelState

Aggiungere il pacchetto Microsoft.AspNetCore.TestHost ed è possibile inviare le richieste di questo semplice:

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

è possibile trovare maggiori informazioni qui: http://asp.net-hacker.rocks/2017/09/27/testing-aspnetcore.html

Speranza che aiuta.

+0

La risposta giusta se stai cercando una risposta .net core. – THBBFT