Как издеваться над вызовом базового метода? - PullRequest
0 голосов
/ 28 апреля 2020

tldr; Как смоделировать вызов базового метода (используя moq)?

Мне нужно найти способ, чтобы обойти проблему, касающуюся насмешки над методом, который принадлежит класс, от которого я наследую, или чтобы на самом деле иметь возможность просто его высмеивать.

Я начну с публикации некоторого кода:

Код для проверки:

public class CustomProductListingService : ProductListingService
{
    public override IEnumerable<Product> ListAllProducts(ICategory category)
    {
        //does some internal filtering and to the developer unkown magic..
        //would like to mock the result of this call..
        var baseResult = base.ListAllProducts(category);

        if(category.Name.StartsWith("A"))
            return baseResult.Where(p => p.Name.StartsWith("A"));
        else if(category.Name.StartsWith("B"))
            return baseResult.Where(p => p.Name.StartsWith("B"));
        else
            return baseResult;
    }
}

Тест:

[TestMethod]
public void CustomProductListingService_ShouldOnlyReturnProductsWithNameStartingWithA() 
{
    //arrange
    var customProductListingService = new CustomProductListingService();
    ICategory category = new category
    {
        Name = "Abcd"
    };

    //act
    var result = customProductListingService.ListAllProducts(category);

    //assert
    foreach(var product in result)
    {
        Assert.IsTrue(product.StartsWith("A"));
    }
}

, как вы можете видеть, я вызываю base.ListAllProducts из моей собственной реализации ListAllProducts, теперь я хотел бы смоделировать base.ListAllProducts, так как мне действительно все равно о том, что этот метод делает внутренне и хочет иметь возможность контролировать результат (возврат), чтобы я мог проверить свою собственную реализацию.

Однако есть и другая проблема, этот код является частью реализации для существующая система, где система обычно просто внедряет ProductListingService с использованием DI, но в моем случае мне потребовалось некоторое пользовательское поведение, и именно поэтому существует CustomProductListingService. То, что я в основном сделал, это переопределил регистрацию системы по умолчанию для ProductListingService, и вместо этого сказал ему ввести мой пользовательский класс CustomProductListingService. В этом случае используемой DI-платформой является StructureMap, поэтому в результате регистрация контейнера в результате выглядела бы примерно так:

            var container = new Container(c =>
            {
                //use system implementation
                c.For<ProductListingService>().Use<ProductListingService>();
                //override system with my implementation
                c.For<ProductListingService>().Use<CustomProductListingService>();
            });

В этом случае возникает проблема, при которой я не могу просто сделать это:

public class CustomProductListingService : ProductListingService
{
    private readonly ProductListingService _productListingService;

    public CustomProductListingService(ProductListingService productListingService)
    {
        this._productListingService = productListingService;
    }

    public override IEnumerable<Product> ListAllProducts(ICategory category)
    {
        //does some internal filtering and to the developer unkown magic..
        //would like to mock the result of this call..
        var baseResult = this._productListingService.ListAllProducts(category);

        if(category.Name.StartWith("A"))
            return baseResult.Where(p => p.Name.StartWith("A"));
        else if(category.Name.StartWith("B"))
            return baseResult.Where(p => p.Name.StartWith("B"));
        else
            return baseResult;
    }
}

Так как это вызвало бы круговую зависимость и было бы странно вводить экземпляр того же типа, что и класс, от которого я наследую. (Если бы это было возможно, я мог бы просто посмеяться над экземпляром, переданным конструктору в качестве параметра).

Есть идеи, как это обойти? Вероятно, следует добавить, что mocking-framework, который я использую, это Moq, если это как-то облегчает решение.

...