在Controller内部声明构造函数,继承ControllerBase

时间:2019-04-11 07:57:12

标签: c# unit-testing asp.net-core asp.net-core-2.0 mstest

我正在研究使用ASP.NET Core 2.1的Web应用程序项目。除了开发API之外,我们还尝试使用MSTest框架对其进行单元测试。

我的控制器继承自ControllerBase。在测试平台中,我正在使用Moq Framework来模拟业务层。当我从测试方法调用Controller时,我需要将Mocked Business实例传递给控制器​​,为此我试图声明参数化构造函数。

它对于测试用例工作正常,但是我的正常流程受到干扰。我什至尝试同时使用参数化和无参数构造函数。

这在继承APIController的Dot Framework上很好用。

public class BookingController: ControllerBase {
    BusinessManager business = new BusinessManager();
    //Non-Parameterized Constructor
    public BookingController() {}
    //Parameterized Constructor
    public BookingController(BusinessManager mockedBusiness) {
        this.business = mockedBusiness;
    }
}

从UI调用时,应使用非参数化的构造函数。 参数化仅在通过一些实例的测试平台调用时才有效。

1 个答案:

答案 0 :(得分:0)

在原始代码中,

BusinessManager business = new BusinessManager();

将控制器与依赖项紧密耦合,并被视为代码异味。这就是为什么您最终不得不尝试一种方法以便能够隔离地测试控制器。

使用explicit dependency principle并保留参数化的构造函数

public class BookingController: ControllerBase {
    private readonly BusinessManager business;

    //Parameterized Constructor
    public BookingController(BusinessManager business) {
        this.business = business;
    }

    //...
}

Startup中,将您的依赖项注册到服务集合中

public void ConfigureServices(IServiceCollection services) {

    //...

    services.AddScoped<BusinessManager>();

    //...

}

这将允许框架在正常流程中创建控制器时在运行时注入所需的依赖关系,并且还允许控制器足够灵活以与您的模拟业务实例进行隔离测试。