簡體   English   中英

在單元測試中正確使用最小起訂量

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM