2-6-4 Tests pour données non valides
Un bon test ne doit pas tester que les conditions de réussite, mais aussi s'assurer que les erreurs et les validations sont bien gérées.
Toujours dans la connexion, on testera les cas d'utilisation dans lesquels:
- Un champ requis est vide
- Le nom d'utilisateur ou mot de passe n’est pas valide
Créer une fonction utilitaire pour connexionViewModelDictionary
Tous les tests de la classe de test AuthTests
auront besoin d'une variation du contenu de la connexionViewModelDictionary
. Plutôt que de recréer l'objet manuellement dans chaque test, on peut créer une fonction responsable de cet aspect qui ne fait que retourner le dictionnaire avec des valeurs.
//...
private Dictionary<string, string> ConnexionViewModelDictionary()
{
return new Dictionary<string, string>
{
{ "Email", "u@ser.com" },
{ "Password", "!User122432" },
};
}
On peut ensuite simplement utiliser cette fonction dans le test plutôt et associer le résultat à la variable connexionViewModelDictionary
.
[Fact]
public async Task Connexion_AuthentificationSucces_RetourneRedirectionAccueil()
{
// Arrange
var client = Application.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
HttpResponseMessage reponse = await client.GetAsync("Auth/Connexion");
reponse.EnsureSuccessStatusCode();
var connexionViewModelDictionary = ConnexionViewModelDictionary();
// Act
IHtmlDocument pageConnexion = await HtmlHelpers.GetDocumentAsync(reponse);
reponse = await client.SendAsync(
(pageConnexion.QuerySelector("main form") as IHtmlFormElement)!,
(pageConnexion.QuerySelector("main form button.btn-primary") as IHtmlButtonElement)!,
connexionViewModelDictionary);
// Assert
Assert.Equal(HttpStatusCode.Redirect, reponse.StatusCode);
Assert.Equal("/", reponse.Headers.Location?.OriginalString);
reponse = await client.GetAsync(reponse.Headers.Location.ToString());
Assert.Contains("Bonjour, Uti", await reponse.Content.ReadAsStringAsync());
}
Tester les erreurs de validation
Pour tester que la validation fonctionne, on peut retirer une des valeurs du formulaire. Par exemple en mettant Password
à String.Empty
.
- Créez une nouvelle fonction de tests
Connexion_AuthentificationInvalide_RetourneErreursValidation
Snowfall.Tests/Web.Mvc/TestsIntegration/AuthTests.cs[Fact]
public async Task Connexion_AuthentificationInvalide_RetourneErreursValidation()
{
} - Pour ce test, on peut retirer un champ de formulaire dans le dictionnaire (ex.: Password):
[Fact]
public async Task Connexion_AuthentificationInvalide_RetourneErreursValidation()
{
// Arrange
var client = Application.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
HttpResponseMessage reponse = await client.GetAsync("Auth/Connexion");
reponse.EnsureSuccessStatusCode();
var connexionViewModelDictionary = ConnexionViewModelDictionary();
connexionViewModelDictionary["Password"] = String.Empty;
// Act
IHtmlDocument pageConnexion = await HtmlHelpers.GetDocumentAsync(reponse);
reponse = await client.SendAsync(
(pageConnexion.QuerySelector("main form") as IHtmlFormElement)!,
(pageConnexion.QuerySelector("main form button.btn-primary") as IHtmlButtonElement)!,
connexionViewModelDictionary);
// Assert
var pageConnexionAvecErreurs = await HtmlHelpers.GetDocumentAsync(reponse);
var elementsErreurValidation = pageConnexionAvecErreurs.QuerySelectorAll(".input-validation-error");
Assert.NotNull(elementsErreurValidation);
Assert.True(elementsErreurValidation.Length > 0);
}
Dans ce test, on met connexionViewModelDictionary["Password"]
à String.Empty
pour générer une erreur de validation.
Ensuite, on vérifie que le retour du serveur contient bien des éléments avec la classe CSS invalid-feedback
, confirmant qu'une validation a échoué.
On pourrait aussi, pour tester toutes les validations, mettre tous les champs pertinents vides et tester le nombre d'erreurs de validation:
[Fact]
public async Task Connexion_AuthentificationInvalide_RetourneErreursValidation()
{
// Arrange
var client = Application.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
HttpResponseMessage reponse = await client.GetAsync("Auth/Connexion");
reponse.EnsureSuccessStatusCode();
var connexionViewModelDictionary = ConnexionViewModelDictionary();
connexionViewModelDictionary["Password"] = String.Empty;
connexionViewModelDictionary["Email"] = String.Empty;
// Act
IHtmlDocument pageConnexion = await HtmlHelpers.GetDocumentAsync(reponse);
reponse = await client.SendAsync(
(pageConnexion.QuerySelector("main form") as IHtmlFormElement)!,
(pageConnexion.QuerySelector("main form button.btn-primary") as IHtmlButtonElement)!,
connexionViewModelDictionary);
// Assert
var pageConnexionAvecErreurs = await HtmlHelpers.GetDocumentAsync(reponse);
var elementsErreurValidation = pageConnexionAvecErreurs.QuerySelectorAll(".input-validation-error");
Assert.NotNull(elementsErreurValidation);
Assert.Equal(2, elementsErreurValidation.Length);
}
Tester l'erreur générique de courriel/mot de passe invalide
Pour tester que l'erreur générique de mauvais nom d'usager ou mot de passe est déclenchée, on peut tester que le div
avec la classe CSS alert alert-danger
est affichée et qu'il contient le message attendu.
[Fact]
public async Task Connexion_MauvaisCourrielMotDePasse_RetourneErreurAlertGenerique()
{
// Arrange
var client = Application.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
HttpResponseMessage reponse = await client.GetAsync("Auth/Connexion");
reponse.EnsureSuccessStatusCode();
var connexionViewModelDictionary = ConnexionViewModelDictionary();
connexionViewModelDictionary["Password"] = "Mauvais mdp!";
// Act
IHtmlDocument pageConnexion = await HtmlHelpers.GetDocumentAsync(reponse);
reponse = await client.SendAsync(
(pageConnexion.QuerySelector("main form") as IHtmlFormElement)!,
(pageConnexion.QuerySelector("main form button.btn-primary") as IHtmlButtonElement)!,
connexionViewModelDictionary);
// Assert
var pageConnexionAvecErreurs = await HtmlHelpers.GetDocumentAsync(reponse);
var elementAlert = pageConnexionAvecErreurs.QuerySelector(".alert.alert-danger");
Assert.NotNull(elementAlert);
Assert.Contains(
"La combinaison de courriel et mot de passe est invalide ou il est impossible de vous identifier",
elementAlert.TextContent);
}