单元测试可以通过接受布尔值作为开关来执行双重任务吗?或者我应该写两个单独的测试来复制测试代码
本文关键字:测试 我应该 两个 复制 代码 单独 或者 布尔值 可以通过 开关 任务 | 更新日期: 2023-09-27 18:21:59
我有一个方法,它的操作依赖于它的依赖项,如下所示。做单元测试仍然有价值吗?因为单元测试不是测试任何业务逻辑,而是通过模拟测试。
以下单元测试:
请注意,该方法的操作由测试设置的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如果没有,单元测试的正确方法是什么?
我不喜欢这样。原因如下:您的测试方法名称应该反映测试中的方法、测试的先决条件以及您期望的测试结果:
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;
}
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();
}
上面的测试将测试服务方法的所有功能,包括是否通过id获取公司,以及是否使用获取的id。此外,它将验证客户是否已添加,是否有效。如果添加了无效的客户,则测试将失败(因为customerRepository是使用MockBehavior.Strict创建的,并且不会执行设置)。