【问题标题】:How to unit test IDataErrorInfo?如何对 IDataErrorInfo 进行单元测试?
【发布时间】:2009-08-21 03:52:28
【问题描述】:

我正在阅读 Asp.net MVC Framework,并且正在阅读有关 IDataErrorInfo 作为验证形式的内容。

所以我只是要发布他所拥有的。

产品类别

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

控制器

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


    }
}

然而,我在书中没有看到如何实际进行单元测试。就像他向您展示了如何对他的服务层内容进行单元测试,但对 IDataErrorInfo 的单元测试却一无所知。

那么我该如何进行单元测试呢?我喜欢检查错误消息以查看它们是否相同。就像我传入一个空字段一样,我想检查错误消息是否适合这个空字段。

在我喜欢在需要验证的东西之后检查 if 语句逻辑以查看它是否正在执行预期的操作,但我什至不知道如何调用这个部分类,特别是因为你通常不想要在进行单元测试时访问数据库。

【问题讨论】:

  • 您发布的产品类是部分的。 Product 类必须有一个或多个附加实现(除其他外)调用部分方法。当我们不知道那是什么样子时,回答您的问题并不容易。此外,我看不到存储库和控制器与此有什么关系,所以也许你可以减少你的问题?

标签: asp.net-mvc unit-testing idataerrorinfo


【解决方案1】:

Matt 提到的解决方案仅适用于我使用后面的声明断言 -

Assert.AreEqual("名称为必填项。", _product["名称"]); - 这对我有用

Assert.AreEqual("名称为必填项。", _product.Error); - 这对我不起作用

【讨论】:

    【解决方案2】:

    单元测试 IDataErrorInfo 非常简单。只需使用对象的“有效”实例设置您的测试,然后测试您是否可以使其出错:

    [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 */
    }
    

    【讨论】:

    • 这似乎不是真的。仅当我在 xaml 中打开 ValidatseOnDataErrors 时,才会在我的应用程序中调用错误索引器 (this[])。在我的测试应用程序中,似乎没有地方打开它,错误索引器永远不会在我的 IDataErrorInfo 业务对象上检查。所以设置 myObject.Name = string.Empty;永远不会检查名称规则。我仍在寻找一种方法来做到这一点。
    • 所以,我们很清楚:我发布了一些测试,因为你不能让它们通过,你给我投反对票?从您的 Error 属性和索引器返回错误!然后测试通过!
    猜你喜欢
    • 1970-01-01
    • 2012-01-08
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    • 2019-01-05
    • 2011-03-16
    • 2013-01-02
    相关资源
    最近更新 更多