[英]Proper use of MOQ in a Unit Test
鑒於以下情況,這是否是最小起訂量的正確使用? 我對“嘲笑”,“竊聽”,“偽造”等等非常陌生,只是想把我的頭纏住。
我的理解是,此模擬提供了已知的結果,因此當我使用該模擬測試該服務時,該服務是否能夠正確響應?
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
IQueryable<T> Query();
}
public interface ICustomerService
{
void CreateCustomer(Customer customer);
Customer GetCustomerById(int id);
}
public class Customer
{
public int Id { get; set; }
}
public class CustomerService : ICustomerService
{
private readonly IRepository<Customer> customerRepository;
public CustomerService(IRepository<Customer> customerRepository)
{
this.customerRepository = customerRepository;
}
public Customer GetCustomerById(int id)
{
return customerRepository.Query().Single(x => x.Id == id);
}
public void CreateCustomer(Customer customer)
{
var existingCustomer = customerRepository.Query().SingleOrDefault(x => x.Id == customer.Id);
if (existingCustomer != null)
throw new InvalidOperationException("Customer with that Id already exists.");
customerRepository.Add(customer);
}
}
public class CustomerServiceTests
{
[Fact]
public void Test1()
{
//var repo = new MockCustomerRepository();
var repo = new Mock<IRepository<Customer>>();
repo.Setup(x => x.Query()).Returns(new List<Customer>() { new Customer() { Id = 1 }}.AsQueryable());
var service = new CustomerService(repo.Object);
Action a = () => service.CreateCustomer(new Customer() { Id = 1 });
a.ShouldThrow<InvalidOperationException>();
}
}
我正在使用xUnit,FluentAssertions和MOQ。
我的理解是,此模擬提供了已知的結果,因此當我使用該模擬測試該服務時,該服務是否能夠正確響應?
該聲明是正確的-單元測試應驗證您正在測試的類(在本例中為CustomerService
)是否表現出所需的行為。 它並不是要驗證其依賴項是否按預期方式運行(在這種情況下,是IRepository<Customer>
)。
您的測試很好*-您正在為IRepository
設置模擬並將其注入到SystemUnderTest中,並驗證CustomerService.CreateCustomer()
函數是否表現出預期的行為。
*測試的總體設置很好,但是我對xUnit並不熟悉,所以最后兩行的語法對我來說是陌生的,但根據語義看來它是正確的。 作為參考,您可以在NUnit中執行最后兩行,如下所示:
Assert.Throws<InvalidOperationException>(() => service.CreateCustomer(...));
該測試對我來說看起來不錯,該模擬程序僅提供了一個偽造的存儲庫,該存儲庫僅為該測試返回了一個硬編碼的答案,因此該測試僅關心您正在測試的服務,而不處理真實數據庫或任何其他內容,因為您不在這里進行測試。
我只會在測試中添加一件事以使其更加完整。 在模擬程序上設置方法調用時,請確保被測試的系統確實調用了它們 。 畢竟,該服務應該向存儲庫詢問某些對象,並僅在某個返回值下拋出。 Moq特別為此提供了一種語法:
repo.VerifyAll();
這樣做只是檢查您之前放置的設置是否至少實際被調用過一次。 這可以保護您避免錯誤,即服務不立即調用該倉庫就立即拋出異常(在您的示例中很容易發現,但是使用復雜的代碼很容易錯過一個調用)。 通過該行,在測試結束時,如果您的服務沒有調用存儲庫的清單(以及特定的參數集),即使正確拋出了異常,測試也將失敗。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.