我是一个需要扩展的项目的新手,因此我决定使用 TDD 来快速识别我不完全理解的系统的任何问题。
有一个名为DBService
的类,它“封装”了所有数据库访问。例如,有一个名为 getAllCustomers
的方法,它返回 Customers
列表。这看起来像这样(这只是为了更好地理解的一个例子):
public class DBService
{
public IDbConnectionFactory DBFactory {
get { return DI.Container.Resolve<IDbConnectionFactory>(); }
}
public List<Customer> GetAllCustomers()
{
try
{
using (var connection = DBFactory.OpenDbConnection())
{
var dbResult = connection.Select<Customer>();
// code ommitted
}
}
catch (Exception e)
{
// code ommitted
}
}
}
另一个问题是,在启动时(在 ServiceStack AppHost.Configure
中),如果表不存在,则会创建所有表,并且对于某些表,如果存在,则会添加一些列等(可能是稍后添加的更改)
例如,当我现在必须扩展客户并添加另一个字段、地址时,我想以 TDD 风格执行此操作,但我不知道如何操作。
- 我无法注入(inject)任何
DBFactory
,因为 getter 是私有(private)的 - 据我所知,我无法对
OrmLiteConnectionFactory
使用:memory:
连接字符串,因为我使用的是 ServiceStack 3.9.74
那么我有什么选择?
最佳答案
避免服务定位器反模式并使用构造函数注入(inject)。尽量避免在依赖类中直接使用 DI 容器。它将您的类与不属于该类的关注点紧密耦合在一起,并使单独测试类变得困难。
public class DBService {
private readonly IDbConnectionFactory connectionFactory;
public DBService(IDbConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public IDbConnectionFactory DBFactory { get { return connectionFactory; } }
public List<Customer> GetAllCustomers() {
try {
using (var connection = DBFactory.OpenDbConnection()) {
var dbResult = connection.Select<Customer>();
//... code omitted for brevity
}
} catch (Exception e) {
//... code omitted for brevity
}
}
}
两者Select<T>
和OpenDbConnection
看起来像扩展方法。我建议检查他们的期望是什么,并 mock 这些行为。
如果DbService
本身要用作其他类的依赖项,那么该类也应该被抽象。
public interface IDbService {
IDbConnectionFactory DBFactory { get; }
List<Customer> GetAllCustomers();
}
并让实现继承
public class DbService : IDbService {
//... code removed for brevity
}
并确保向 IoC 容器注册所有内容。
关于c# - 如何对使用 Servicestack Funq IOC 的 DBService 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41957605/