单元测试 - 添加新产品

时间:2014-03-11 10:22:48

标签: c# unit-testing mstest

大家好,我对单元测试很新。我的方案:我有一个产品业务逻辑层,在add / update等产品服务方法中有以下类和接口(productproductCategory,接口IProductRepositoryProductService) /删除已实现。我想在添加产品时编写单元测试。下面是我的代码,但我不确定我是否正确执行。

测试方案 1)当我添加新产品时检查过期日期是否大于当前日期
2)当我添加新产品时,价格必须大于0
3)不要添加删除标志设置为false的产品 4)当我添加产品类别名称时,不应该为空/空白

我真的很感激,如果有人可以指出我正确的方向,特别是在断言方面。 代码

在ProductService类中保存方法

   public Boolean save(Product product)
   {
       Boolean flg = false;
       if ( (product.Expire > DateTime.Now && product.Price > 0 )
        && (product.flg =true))
       {

           flg = true;

       }
       return flg;
   }

单元测试

[TestClass()]
public class ProductServiceTests
{
    ProductService Objproductservice;
    List<Product> ProductList;
    Product product1;
    Product product2;
    Product product3;
    DateTime time;
    Boolean flg;

    [TestInitialize]
    public void Setup()
    {
      flg = false;
      product1 = new Product { ProductId = 1, Name = "Ice Cream Ben&Jerry", Description = "Dairy", Expire = DateTime.Now.AddDays(20), DateModified = DateTime.Now, Price = 3.99, flg = true, CatID=2, CategoryName="Dairy" };
      product2 = new Product { ProductId = 1, Name = "Rice Basmati", Description = "Grocery", Expire = DateTime.Now.AddDays(20), DateModified = DateTime.Now, Price = 7.99, flg = false, CatID = 1002, CategoryName = "Grocery" };

    }


    [TestMethod]
    public void when_save_product_expire_date_greater_current_date()
    {

        Objproductservice = new ProductService();
        flg = Objproductservice.save(product1);

        Assert.IsTrue(product1.Expire > DateTime.Now);
        Assert.IsTrue(flg);
    }

    [TestMethod()]
    public void when_save_product_price_greater_than_zero()
    {

        Objproductservice = new ProductService();
        flg = Objproductservice.save(product1);

        Assert.IsTrue(product1.Price > 0);
        Assert.IsTrue(flg);
    }

    [TestMethod]
    public void do_not_save_product_if_delete_flg_isFalse()
    {

        Objproductservice = new ProductService();
        flg = Objproductservice.save(product2);

        Assert.IsFalse(product2.flg);
        Assert.IsFalse(flg);
    }

    [TestMethod]
    public void when_add_product_stock_level_increate()
    {

    }

    [TestMethod]
    public void when_save_product_categoryName_should_not_be_null()
    {

        Objproductservice = new ProductService();
        flg = Objproductservice.save(product1);

        string CategoryName = product1.CategoryName;
        Assert.IsTrue(CategoryName.Length > 0);
        Assert.IsTrue(flg);
    }

}

1 个答案:

答案 0 :(得分:3)

我建议您遵循Tell Don't Ask原则,而不是要求产品的到期日期,价格等 - 告诉他自己检查(顺便说一句,IsExpired可以,但考虑禁止将无效价格设置为产品):

public class Product
{
    public DateTime Expire { get; set; }
    public decimal Price { get; set; }

    public virtual bool IsExpired
    { 
        get { return Expire > DateTime.Now; }
    }

    public virtual bool IsValid
    {
        get { return !IsExpired && Price > 0; }
    }
}

现在您可以创建过期或价格无效的不同产品并将其传递给服务:

ProductService service;
Mock<IProductRepository> repositoryMock;
Mock<Product> productMock;

[TestInitialize]
public void Setup()
{      
    repositoryMock = new Mock<IProductRepository>();
    service = new ProductService(repositoryMock.Object);
    productMock = new Mock<Product>();
}

[TestMethod]
public void Should_not_save_invalid_product()
{
    productMock.SetupGet(p => p.IsValid).Returns(false);
    bool result = service.save(productMock.Object);

    Assert.False(result);
    repositoryMock.Verify(r => r.Save(It.IsAny<Product>()),Times.Never());
}

[TestMethod]
public void Should_save_valid_product()
{
    productMock.SetupGet(p => p.IsValid).Returns(true); 
    repositoryMock.Setup(r => r.Save(productMock.Object)).Returns(true);

    bool result = service.save(productMock.Object);

    Assert.True(result);
    repositoryMock.VerifyAll();
}  

服务的实施如下:

public bool save(Product product)
{
    if (!product.IsValid)
        return false;

    return repository.Save(product);
}

接下来编写Product测试以验证IsValid是否正常工作。您可以使用允许模拟静态成员的单元测试框架(例如TypeMock),或者您可以使用Factory创建产品并向其注入ITimeProvider实现。那将允许你模拟时间提供者。或者很好的组合解决方案 - 创建自己的静态时间提供程序,允许设置值:

public static class TimeProvider
{        
    private static Func<DateTime> currentTime { get; set; }

    public static DateTime CurrentTime
    {
        get { return currentTime(); }
    }

    public static void SetCurrentTime(Func<DateTime> func)
    {
        currentTime = func;
    }
}

使用此提供商代替DateTime.Now

public virtual bool IsExpired
{ 
    get { return Expire > TimeProvider.CurrentTime; }
}

现在您可以为产品提供当前时间和编写测试:

private DateTime today;

[TestInitialize]
public void Setup()
{      
    today = DateTime.Today;
    TimeProvider.SetCurrentTime(() => today);
}

[TestMethod]
public void Should_not_be_valid_when_price_is_negative()
{
    Product product = new Product { Price = -1 };
    Assert.False(product.IsValid);
}

[TestMethod]
public void Should_be_expired_when_expiration_date_is_before_current_time()
{        
    Product product = new Product { Expire = today.AddDays(-1) };
    Assert.False(product.IsExpired);
}

// etc