简体   繁体   English

抽象具有扩展方法的类的接口

[英]abstracting an interface to a class that has extension methods

How do I replace a concrete class with its interface for the purpose of unit testing if I am using extension methods in that class? 如果我在类中使用扩展方法,如何用其接口替换具体的类以进行单元测试?

I've got a method: 我有一个方法:

[HttpGet]
[Route("/yoyo/{yoyoId:int}/accounts")]
public ResponseYoyoEnvelope GetAccountsByYoyoId([FromBody] RequestYoyoEnvelope requestYoyoEnvelope, int yoyoId)
{
    var responseYoyoEnvelope = requestYoyoEnvelope.ToResponseYoyoEnvelope();

    // get our list of accounts
    // responseEnvelope.Data = //list of accounts
    return responseYoyoEnvelope;
}

I'd like to replace: 我要替换:

RequestYoyoEnvelope requestYoyoEnvelope

with an abstraction: 带有抽象:

IRequestYoyoEnvelope requestYoyoEnvelope

however, ToResponseYoyoEnvelope is an extension method. 但是, ToResponseYoyoEnvelope是一种扩展方法。

How do I replace a concrete class with its interface for the purpose of unit testing if I am using extension methods in that class? 如果我在类中使用扩展方法,如何用其接口替换具体的类以进行单元测试?

You can write the extension method against the interface rather than the concrete class: 您可以针对接口而不是具体的类编写扩展方法:

public static class Class2
{
    public static void Extension(this ITestInterface test)
    {
        Console.Out.WriteLine("This is allowed");
    }
}

Then you can do: 然后,您可以执行以下操作:

// "Test" is some class that implements the ITestInterface interface
ITestInterface useExtensionMethod = new Test();
useExtensionMethod.Extension();

Note too that this'll still work even if useExtensionMethod isn't explicitly of type ITestInterface : 还要注意,即使useExtensionMethod不是显式为ITestInterface类型,这仍然可以ITestInterface

Test useExtensionMethod = new Test();
useExtensionMethod.Extension();

There's controversy about whether this represents a Decorator pattern but keep in mind at a minimum that the Extension method isn't literally a part of the interface itself - it's still a static method "under the hood," it's just that the compiler's allowing you the convenience of treating this like an instance method. 关于这是否代表Decorator模式存在争议 ,但至少要记住,Extension方法实际上不是接口本身的一部分- 它仍然是 “隐藏” 的静态方法 ,只是编译器允许您使用将其像实例方法一样方便。

Assuming 假设

public class RequestYoyoEnvelope : IRequestYoyoEnvelope { ... }

Your extension method would need to target the interface 您的扩展方法将需要定位接口

public static ResponseYoyoEnvelope ToResponseYoyoEnvelope(this IRequestYoyoEnvelope target) { ... }

Keep the action as is because the model binder will have issues binding the interface. 保持动作不变,因为模型绑定器在绑定接口时会遇到问题。

In your unit test you pass a concrete implementation of RequestYoyoEnvelope and the updated extension method should be able to be tested. 在单元测试中,您通过了RequestYoyoEnvelope的具体实现,并且应该能够测试更新的扩展方法。

From your example you would not need an interface to test if that method is the method under test. 从您的示例中,您不需要接口即可测试该方法是否为被测试方法。 just new up an instance of the model and pass it to the method during the unit test. 只是新建一个模型实例,并在单元测试期间将其传递给方法。

[TestMethod]
public void GetAccountsByYoyoIdTest() {
    //Arrange
    var controller = new YoyoController();
    var yoyoId = 123456;
    var model = new RequestYoyoEnvelope {
        //you populate properties for test
    };
    //Act
    var result = controller.GetAccountsByYoyoId(model, yoyoId);

    //Assert
    //...do your assertions.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM