1

Je suis en train d'écrire des tests unitaires pour un automate ASP.NET MVC 2 et j'ai quelques problèmes avec les attributs de validation MVC 2.0. L'attribut de validation en question utilise un référentiel pour vérifier qu'il n'existe pas de noms en double dans la source de données actuelle, et je souhaite remplacer ce référentiel par un faux lors de mon test unitaire. J'utilise Castle Windsor, comme au this article, ce qui me permet de remplacer le dépôt au moment de l'exécution, mais je ne suis pas sûr de savoir comment je peux le faire pendant le test unitaire.Test d'unité de validation d'attribut MVC 2 avec IoC

La majeure partie du code de test est la suivante:

[TestMethod] 
    public void TestSaveDuplicateTitleNameReturnsValidationErrorView() 
    { 
     //Arrange 
     var titleRepository = new FakeTitleRepository(); 
     var controller = new TitleController(titleRepository);    

     var selectedTitle = new Title(); 
     selectedTitle.Name = "Fru"; 

     //Act 
     var actual = controller.Save(selectedTitle); 

Un exemple de code du contrôleur est ci-dessous:

public ActionResult Save(Title SelectedTitle) 
    { 
     if (TryValidateModel(SelectedTitle)) 
     { 
      TitleRepository.Add(SelectedTitle); 
      TitleRepository.Save(); 

Le référentiel utilisé dans le contrôleur lui-même lors de l'essai est mon faux celui que j'ai passé, mais lorsque le TryValidateModel se déclenche et que le code suivant est exécuté, il provoque une exception car le référentiel est null:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] 
public class ValidTitleNameAttribute : ValidationAttribute 
{ 
    public ITitleRepository Repository { get; set; } 

    public override bool IsValid(object value) 
    { 
     bool isValid = true; 

     PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value); 
     object name = properties.Find("Name", true).GetValue(value); 

     if (name == null) 
     { 
      return isValid = false; 
     } 

     var titles = Repository.GetAllTitles(); 

Évidemment, dans la propriété du référentiel, je pourrais définir une instance par défaut pour référencer un référentiel concret, ce qui empêcherait l'exception pendant le test, mais cela irait à l'encontre du but de l'utilisation du conteneur IoC. Quelle serait la meilleure façon de contourner ce problème, serait-ce de trouver un moyen de se moquer de l'attribut de validation d'une manière ou d'une autre, ou y a-t-il un moyen pour Windsor d'injecter le faux référentiel? Toute aide/conseil serait très apprécié.

+0

le contrôleur doit avoir un constructeur gourmand prenant l'interface du référentiel qu'il utilise, puis dans la méthode de test, ajouter le faux dépôt à la place. Vous pouvez laisser l'instanciation de l'interface à di à la place afin de conserver la séparation des préoccupations. – Joakim

Répondre

1

Je pense que la meilleure chose à faire serait de créer un faux DataAnnotationsModelValidator pour votre test unitaire qui injectera votre faux dépôt pendant les tests. Vous devriez être capable de le rendre assez simple afin de limiter les risques de problèmes avec vos tests unitaires.