6

我有一个方法,其操作取决于其依赖项,如下所示。进行单元测试仍然有价值吗?因为单元测试不是测试任何业务逻辑,而是通过模拟。

下面的单元测试:

请注意,该方法的选项由 确定expectedCustomerValidality,由测试设置。大多数情况下,逻辑由模拟(例如Setup(c => c.IsValid()).

        [Test]
        [TestCase(true)]
        [TestCase(false)]
        public void AddCustomer(bool expectedCustomerValidality)
        {
           //using Moq
            companyRepositoryMock.Setup(c => c.GetById(It.IsAny<int>())).Returns(new Company());          
            customerValidatorMock.Setup(c => c.IsValid(It.IsAny<Customer>())).Returns(expectedCustomerValidality);

            var customer = new Customer
                               {
                                   Firstname = "firstName",
                                   Surname = "surname",
                                   Company = new Company { Id = 1 }
                               };

            var addCustomer = customerServiceSut.AddCustomer(customer);

            Assert.AreEqual(expectedCustomerValidality,addCustomer);
        }

生产代码如下:

 public class CustomerService : ICustomerService
    {
        private ICompanyRepository companyRepository;
        private ICustomerRepository customerRepository;
        private ICustomerValidator customerValidator;

        public CustomerService(ICompanyRepository companyRepository, ICustomerRepository customerRepository, ICustomerValidator customerValidator)
        {
            this.companyRepository = companyRepository;
            this.customerRepository = customerRepository;
            this.customerValidator = customerValidator;

        }

        public bool AddCustomer(Customer customer)
        {           
            customer.Company = companyRepository.GetById(customer.Company.Id); ;

            if (customerValidator.IsValid(customer))
            {
                customerRepository.AddCustomer(customer);

                return true;
            }

            return false;
        }
}

问题:

  • AddCustomer() 是否需要单元测试?
  • 如果是这样,当前的单元测试是否以正确的方式执行?

    1 如果不是,那么单元测试的正确方法是什么?

4

2 回答 2

7

我不喜欢这个。原因如下:您的测试方法名称应该反映被测方法、测试的前提条件以及您期望的测试结果:

public bool AddCustomer_CustomerIsValid_ShouldReturnTrue()

public bool AddCustomer_CustomerIsInvalid_ShouldReturnFalse()

现在,如果您愿意,您可以将核心测试逻辑重构为自己的方法以消除代码重复,然后从上述两个方法中调用该方法。但是重构的方法不是测试用例;它只是实际测试用例的辅助方法。

例子:

[Test]
public void AddCustomer_CustomerIsValid_ShouldReturnTrue()
{
    var result = AddCustomerTest(true);
    Assert.IsTrue(result);
}

[Test]
public void AddCustomer_CustomerIsInvalid_ShouldReturnFalse()
{
    var result = AddCustomerTest(false);
    Assert.IsFalse(result);
}

public void AddCustomerTest(bool expectedCustomerValidality)
{
   //using Moq
    companyRepositoryMock.Setup(c => c.GetById(It.IsAny<int>())).Returns(new Company());          
    customerValidatorMock.Setup(c => c.IsValid(It.IsAny<Customer>())).Returns(expectedCustomerValidality);

    var customer = new Customer
    {
        Firstname = "firstName",
        Surname = "surname",
        Company = new Company { Id = 1 }
    };

    var result= customerServiceSut.AddCustomer(customer);

    return result;
}
于 2013-07-12T02:37:45.790 回答
0

AddCustomer需要测试,因为它执行业务逻辑 - 它检索公司,设置它,验证数据,将数据添加到存储库,并返回结果。

你的测试几乎是正确的。我会让它更具体一点,以验证所有业务逻辑:

[Test]
[TestCase(true)]
[TestCase(false)]
public void AddCustomer(bool isCustomerValid)
{
     //arrange
     //NOTE!!! create the mocks with MockBehavior.Strict
     //that way the test will fail if a call is made w/o setup

     const long testCompanyId = 100;
     var testCompany = new Company{ Id = testCompanyId };
     companyRepository.Setup(r => r.GetById(testCompanyId))
          .Returns(testCompany);

     var testCustomer = new Customer
                   {
                        Firstname = "firstName",
                        Surname = "surname",
                        Company = new Company { Id = testCompanyId }
                   };

     customerValidatorMock.Setup(c => c.IsValid(It.Is<Customer>(c => c == testCustomer && c.Company == testCompany)).Returns(isCustomerValid);

     if (isCustomerValid)
     {
          customerRepository.Setup( r => r.AddCustomer(testCustomer) ). Verifiable();
     }

     //act        
     var addCustomerResult = customerServiceSut.AddCustomer(testCustomer);

     //assert
     Assert.AreEqual(isCustomerValid, addCustomerResult);
     cutomerRepository.VerifyAll();
}

上面的测试会测试 service 方法的所有功能,包括是否通过 id 获取 company 以及是否使用了获取的那一个。此外,它将验证客户是否已添加,是否有效。如果添加了无效的客户,则测试将失败(因为 customerRepository 是使用 MockBehavior.Strict 创建的,并且不会执行设置)。

于 2013-07-15T16:13:38.760 回答