【问题标题】:Declaring constructor inside Controller inheriting ControllerBase在继承ControllerBase的Controller中声明构造函数
【发布时间】:2019-04-11 07:57:11
【问题描述】:

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

我的控制器继承自 ControllerBase。在我的测试台中,我正在使用 Moq 框架模拟我的业务层。当我从测试方法调用控制器时,我需要将一个模拟业务实例传递给控制器​​,我正在尝试为其声明参数化构造函数。

测试用例运行良好,但我的正常流程受到干扰。我什至尝试使用参数化和无参数构造函数。

这适用于继承 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 调用时应使用非参数化构造函数。 参数化应该只在从测试台调用传递一些实例时才起作用。

【问题讨论】:

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


    【解决方案1】:

    在原代码中,

    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>();
    
        //...
    
    }
    

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

    【讨论】:

    • 它现在按预期工作。但是,这是正确的方法吗?因为假设我有 10 个 BLL 类,那么根据建议我需要添加 10 个 AddScoped 方法。在某处我觉得它不正确
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 2014-11-14
    • 2018-06-06
    • 2015-11-08
    • 1970-01-01
    相关资源
    最近更新 更多