依赖注入 - 添加客户对象导致测试失败
Dependency Injection - adding Customer object causing test to fail
我在类的存储库上使用了构造函数注入,我注意到以下工作:
public CreateInvoiceResult CreateInvoice(string Code, int qty, string Name)
{
if (string.IsNullOrEmpty(Code) || qty <= 0 || repository.GetByName(Name).ID <= 0)
{
return new CreateInvoiceResult(false);
}
但是更改为以下代码(添加 'Customer cust')会导致测试失败?
public CreateInvoiceResult CreateInvoice(string stockCode, int quantity, string customerName)
{
Customer cust = repository.GetByName(Name);
if (string.IsNullOrEmpty(Code) || qty <= 0 || cust.ID <= 0)
{
return new CreateInvoiceResult(false);
}
示例测试:
请解释为什么会这样,我该如何纠正?
编辑:已使用 Moq 更新测试,以使用正确的存储库:
[TestClass]
public class MockCustomerRepositoryDBTests
{
public MockCustomerRepositoryDBTests()
{
IList<Customer> customers = new List<Customer>
{
new Customer { ID = 1, Name = "Jim Smith",
Address = "14 Main Road"},
new Customer { ID = 2, Name = "Alex Smith",
Address = "78 Avanue"},
new Customer { ID = 3, Name = "Paul Brown",
Address = "1 Main Road"}
};
// Mock the CustomerRepositoryDB Repository using Moq
Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
// Return a customer by Name
mockCustomerRepository.Setup(mr => mr.GetByName(
It.IsAny<string>())).Returns((string s) => customers.Where(
x => x.Name == s).Single());
// Complete the setup of the Mock Customer Repository
this.MockCustomerRepository = mockCustomerRepository.Object;
}
public readonly ICustomerRepository MockCustomerRepository;
[TestMethod]
public void stockCodeIsNullOrEmpty()
{
//Arrange
var x = new InvoiceController(MockCustomerRepository);
//Act
bool result = x.CreateInvoice("", 1, "test").Success;
//Assert
Assert.AreEqual(result, false);
}
获得'System.InvalidOperationException: Sequence contains no elements'
你打给
的电话
Customer _Customer = repository.GetByName(customerName);
可能会失败,但有一些例外。
如果您查看 class,您仅在此构造函数中初始化存储库对象:
public PartInvoiceController(ICustomerRepository custRepo)
{
this.repository = custRepo;
}
但是你提供了一个在测试中调用的默认构造函数:
//Arrange
var x = new PartInvoiceController();
因此您的存储库永远不会被初始化,因此您将得到一个空引用异常。
为什么之前没有失败?
当它是 if 语句的一部分时,它并不重要,因为它从未执行过,因为 string.IsNullOrEmpty(stockCode)
为真,其他条件使用 conditional-or operator (||) 组合,这将缩短-电路评估条件,如果它可以判断条件将是真还是假,即使所有条件都没有被评估。
因此输入了 if 语句,并且从未评估其他条件,因此存储库为 null 是从未执行过的代码。
要更正它,您需要提供一个要在测试中使用的存储库(存根或模拟),或者在默认构造函数中创建一个默认存储库,或者恢复到原始代码(只要您不这样做)我不关心存储库在这个测试中没有被初始化)。
像这样更改您的测试:
[TestMethod]
public void stockCodeIsNullOrEmpty()
{
ICustomerRepository testRepository = //create a test repository here
//Arrange
var x = new PartInvoiceController(testRespository);
//Act
bool result = x.CreatePartInvoice("", 1, "test").Success;
//Assert
Assert.AreEqual(result, false);
}
编辑
真的,你应该问另一个关于你的模拟问题的问题,但基本上你正在寻找一个名为 "test" 的用户,但是模拟存储库中的 none 个用户有这个名字
Customer _Customer = repository.GetByName(customerName);
成员变量"repository"在使用前没有初始化。您应该使用 class PartInvoiceController 的另一个构造函数。
我在类的存储库上使用了构造函数注入,我注意到以下工作:
public CreateInvoiceResult CreateInvoice(string Code, int qty, string Name)
{
if (string.IsNullOrEmpty(Code) || qty <= 0 || repository.GetByName(Name).ID <= 0)
{
return new CreateInvoiceResult(false);
}
但是更改为以下代码(添加 'Customer cust')会导致测试失败?
public CreateInvoiceResult CreateInvoice(string stockCode, int quantity, string customerName)
{
Customer cust = repository.GetByName(Name);
if (string.IsNullOrEmpty(Code) || qty <= 0 || cust.ID <= 0)
{
return new CreateInvoiceResult(false);
}
示例测试:
请解释为什么会这样,我该如何纠正?
编辑:已使用 Moq 更新测试,以使用正确的存储库:
[TestClass]
public class MockCustomerRepositoryDBTests
{
public MockCustomerRepositoryDBTests()
{
IList<Customer> customers = new List<Customer>
{
new Customer { ID = 1, Name = "Jim Smith",
Address = "14 Main Road"},
new Customer { ID = 2, Name = "Alex Smith",
Address = "78 Avanue"},
new Customer { ID = 3, Name = "Paul Brown",
Address = "1 Main Road"}
};
// Mock the CustomerRepositoryDB Repository using Moq
Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
// Return a customer by Name
mockCustomerRepository.Setup(mr => mr.GetByName(
It.IsAny<string>())).Returns((string s) => customers.Where(
x => x.Name == s).Single());
// Complete the setup of the Mock Customer Repository
this.MockCustomerRepository = mockCustomerRepository.Object;
}
public readonly ICustomerRepository MockCustomerRepository;
[TestMethod]
public void stockCodeIsNullOrEmpty()
{
//Arrange
var x = new InvoiceController(MockCustomerRepository);
//Act
bool result = x.CreateInvoice("", 1, "test").Success;
//Assert
Assert.AreEqual(result, false);
}
获得'System.InvalidOperationException: Sequence contains no elements'
你打给
的电话Customer _Customer = repository.GetByName(customerName);
可能会失败,但有一些例外。
如果您查看 class,您仅在此构造函数中初始化存储库对象:
public PartInvoiceController(ICustomerRepository custRepo)
{
this.repository = custRepo;
}
但是你提供了一个在测试中调用的默认构造函数:
//Arrange
var x = new PartInvoiceController();
因此您的存储库永远不会被初始化,因此您将得到一个空引用异常。
为什么之前没有失败?
当它是 if 语句的一部分时,它并不重要,因为它从未执行过,因为 string.IsNullOrEmpty(stockCode)
为真,其他条件使用 conditional-or operator (||) 组合,这将缩短-电路评估条件,如果它可以判断条件将是真还是假,即使所有条件都没有被评估。
因此输入了 if 语句,并且从未评估其他条件,因此存储库为 null 是从未执行过的代码。
要更正它,您需要提供一个要在测试中使用的存储库(存根或模拟),或者在默认构造函数中创建一个默认存储库,或者恢复到原始代码(只要您不这样做)我不关心存储库在这个测试中没有被初始化)。
像这样更改您的测试:
[TestMethod]
public void stockCodeIsNullOrEmpty()
{
ICustomerRepository testRepository = //create a test repository here
//Arrange
var x = new PartInvoiceController(testRespository);
//Act
bool result = x.CreatePartInvoice("", 1, "test").Success;
//Assert
Assert.AreEqual(result, false);
}
编辑
真的,你应该问另一个关于你的模拟问题的问题,但基本上你正在寻找一个名为 "test" 的用户,但是模拟存储库中的 none 个用户有这个名字
Customer _Customer = repository.GetByName(customerName);
成员变量"repository"在使用前没有初始化。您应该使用 class PartInvoiceController 的另一个构造函数。