数据访问,单元测试,依赖注入

Dev*_*Dev 3 unit-testing dependency-injection data-access

我最近有一项任务是创建一个简单的实用程序,它允许将数据从具有特殊格式的文件导入数据库.我已经实现了几个类的控制台应用程序(Program类与业务逻辑类一起运行,业务逻辑类又与数据访问类一起运行).一切正常,但现在我正在考虑创建一些单元测试和重构应用程序(我之前没有创建过真正的单元测试,很久以前只是一堆集成测试,所以我相信这个应用程序是完美的实践领域) .

所以,问题是:数据访问类已经变为静态,这不允许模拟它,因此创建真正的单元测试.要解决这个问题,我需要创建一个接口并在数据访问类中实现它.此外,我将不得不向业务逻辑类添加一个构造函数,该类将接受该接口类型的参数.所以这意味着我将最终在应用程序Main()方法中创建数据访问类,并且有些东西告诉我这不是最好的方法(入口点是否应该知道一些数据访问事项?如果链是更长或应该有几个链?).我知道我可以使用一些IoC容器,但我认为这是一个太简单的应用程序来使用容器.

谢谢!

Jef*_*nal 5

我需要创建一个接口并在数据访问类中实现它.此外,我将不得不向业务逻辑类添加一个构造函数,该类将接受该接口类型的参数.所以这意味着我将最终在应用程序Main()方法中创建数据访问类,并且有些东西告诉我这不是最好的方法(入口点是否应该知道一些数据访问事项?如果链是更长或应该有几个链?)

反之!这最好的方法,至少从可测试性的角度来看.

使业务逻辑层可测试的唯一方法是通过完全按照您的考虑将其与数据访问层隔离开来.

您的顶级应用程序是降压停止的地方 - 它是唯一需要知道具体数据访问类是什么的组件.

如果链条更长或有多个链条,这没什么大不了的(尽管如果它失控,你可能会考虑折叠一些应用程序层).在Model-View-Presenter应用程序中考虑这个潜在的代码View,其中Presentera依赖于a CustomerService,它依赖于a Repository和依赖于a AccountingService(也依赖于Repository):

public CustomerView() {
    IRespository       repository        = new ConcreteRepository();
    IAccountingService accountingService = new ConcreteAccountingService(repository);
    ICustomerService   customerService   = new ConcreteCustomerService(accountingService, repository)
    this._Presenter = new CustomerPresenter(customerService);
}
Run Code Online (Sandbox Code Playgroud)

最后,如果你不想使用依赖注入容器(虽然其中一些是令人惊讶的轻量级) - 手动依赖注入工作正常,直到你开始在整个地方重复自己(或发现你想要配置)运行时的依赖关系).