2009-08-21 7 views
-1

Je lis Asp.net MVC Framework et je lis sur IDataErrorInfo comme forme de validation.Comment tester unit IDataErrorInfo?

Alors je vais juste poster ce qu'il a.

Classe de produits

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 

namespace MvcApplication1.Models 
{ 
    public partial class Product : IDataErrorInfo 
    { 

     private Dictionary<string, string> _errors = new Dictionary<string, string>(); 

     partial void OnNameChanging(string value) 
     { 
      if (value.Trim() == String.Empty) 
       _errors.Add("Name", "Name is required."); 
     } 


     partial void OnPriceChanging(decimal value) 
     { 
      if (value <= 0m) 
       _errors.Add("Price", "Price must be greater than 0."); 
     } 


     #region IDataErrorInfo Members 

     public string Error 
     { 
      get { return string.Empty; } 
     } 

     public string this[string columnName] 
     { 
      get 
      { 
       if (_errors.ContainsKey(columnName)) 
        return _errors[columnName]; 
       return string.Empty; 
      } 
     } 

     #endregion 


    } 
} 

ProductRepository.

using System.Collections.Generic; 
using System.Linq; 

namespace MvcApplication1.Models 
{ 
    public class ProductRepository : IProductRepository 
    { 
     private ProductsDBEntities _entities = new ProductsDBEntities(); 

     public IEnumerable<Product> ListProducts() 
     { 
      return _entities.ProductSet.ToList(); 
     } 

     public void CreateProduct(Product productToCreate) 
     { 
      _entities.AddToProductSet(productToCreate); 
      _entities.SaveChanges(); 
     } 

    } 

    public interface IProductRepository 
    { 
     IEnumerable<Product> ListProducts(); 
     void CreateProduct(Product productToCreate); 
    } 
} 

Contrôleur

using System.Web.Mvc; 
using MvcApplication1.Models; 

namespace MvcApplication1.Controllers 
{ 
    public class ProductController : Controller 
    { 
     private IProductRepository _repository; 

     public ProductController() 
      :this(new ProductRepository()){} 


     public ProductController(IProductRepository repository) 
     { 
      _repository = repository; 
     } 


     public ActionResult Index() 
     { 
      return View(_repository.ListProducts()); 
     } 


     // 
     // GET: /Product/Create 

     public ActionResult Create() 
     { 
      return View(); 
     } 

     // 
     // POST: /Product/Create 

     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult Create([Bind(Exclude="Id")]Product productToCreate) 
     { 
      if (!ModelState.IsValid) 
       return View(); 
      _repository.CreateProduct(productToCreate); 
      return RedirectToAction("Index"); 
     } 


    } 
} 

Pourtant, Nulle part dans le livre ce que je vois comment effectivement ce test unitaire. Comme il vous montre comment tester unitairement sa couche de service, mais rien sur le test unitaire IDataErrorInfo.

Alors, comment pourrais-je tester cela? J'aime vérifier les messages d'erreur pour voir s'ils sont identiques. Comme si je passe dans un champ nul, j'aime vérifier si le message d'erreur serait le bon pour ce champ nul. Après je voudrais vérifier si la logique d'instruction après la substance qui doit être validée pour voir si elle fait ce qui est attendu, mais je ne sais même pas comment appeler cette classe partielle, d'autant plus que vous ne le faites pas normalement vouloir frapper la base de données lors de tests unitaires.

+1

La classe de produit que vous avez affichée est partielle. Il doit y avoir une ou plusieurs implémentations supplémentaires de la classe Product qui invoquent (entre autres choses) les methdods partiels. Ce n'est pas très facile de répondre à votre question quand on ne sait pas à quoi ça ressemble. De plus, je ne vois pas comment le référentiel et le contrôleur ont quelque chose à voir avec cela, alors peut-être pourriez-vous réduire votre question? –

Répondre

1

Tests unitaires IDataErrorInfo est assez facile. Il suffit de configurer vos tests avec une instance de l'objet « valide », puis test que vous pouvez le faire erreur:

[TestFixture] 
public class ErrorTests 
{ 
    private Product _product; // subject under test 

    [SetUp] 
    public void Create_valid_instance() 
    { 
     _product = new Product { /* valid values */ }; 
    } 

    [Test] 
    public void Name_cannot_be_null() 
    { 
     _product.Name = null; 
     Assert.AreEqual("Name is required.", _product.Error); 
     Assert.AreEqual("Name is required.", _product["Name"]); 
    } 

    [Test] 
    public void Name_cannot_be_empty() 
    { 
     _product.Name = String.Empty; 
     Assert.AreEqual("Name is required.", _product.Error); 
     Assert.AreEqual("Name is required.", _product["Name"]); 
    } 

    [Test] 
    public void Name_cannot_be_whitespace() 
    { 
     _product.Name = " "; 
     Assert.AreEqual("Name is required.", _product.Error); 
     Assert.AreEqual("Name is required.", _product["Name"]); 
    } 

    /* etc - add tests to prove that errors can occur */ 
} 
+1

Cela ne semble pas être vrai. L'indexeur d'erreur (this []) n'apparaît que dans mon application lorsque j'active ValidatseOnDataErrors dans mon xaml. Dans mon application de test, qui semble manquer d'un emplacement pour l'activer, l'indexeur d'erreurs n'est jamais vérifié sur mes objets métier IDataErrorInfo. Donc, en définissant myObject.Name = string.Empty; ne vérifiera jamais la règle de nom. Je cherche toujours un moyen de le faire. – Bob

+0

D'accord avec Bob. Cela ne fonctionne pas totalement ... – CamronBute

+1

Donc, juste pour que nous soyons clairs: je poste des tests, et parce que vous ne pouvez pas les faire passer, vous me donnez des downvotes? Renvoie l'erreur de votre propriété Error ainsi que l'indexeur! Alors les tests passent! –

2

La solution mentionnée par Matt ne fonctionne que pour moi si j'utilise la déclaration plus tard Affirmez -

Assert.AreEqual ("Name is required.", _product ["Nom"]); - Cela fonctionne pour moi

Assert.AreEqual ("Name is required.", _product.Error); - cela ne fonctionne pas pour moi