我有一个webAPI应用程序,它有一个Repository层,DTO服务层和WebAPI层。 WebAPI调用DTO调用Repository。
我的存储库开头是这样的:
public class RepositoryService : IRepositoryService
{
private readonly DbContext _db;
public RepositoryService(string connectionString)
{
_db = new DbContext(connectionString);
}
public RepositoryService()
{
_db = new DbContext();
}
我的DTO服务就是这样开始的:
public class DtoService : IDtoService
{
private readonly RepositoryService _repository;
public DtoService(string connectionString)
{
_repository = new RepositoryService(connectionString);
}
public DtoService()
{
_repository = new RepositoryService();
}
我的DbContext看起来像这样:
public DbContext() : base("name=TestConnection")
{
}
public DbContext(string connectionString) : base(connectionString)
{
}
到目前为止,这使我可以选择定义在运行测试应用程序时使用的连接字符串。
第一个问题:这种做法看起来不错吗?
现在我已经接受了我的WebAPI层,我不仅仅有一个控制器类。我有一堆不同的控制器。我正在考虑为每个控制器完成并实现这些构造函数,但是必须有更好的方法来实现这一点。有些东西告诉我这是依赖注入发挥作用的地方,但我不确定。
我可以这样做:
在我的测试中,新建了每个控制器的实例,如
var accountController = new AccountController(connectionStringForTesting)
但我知道这不实用,所以......
第二个问题:实用的方法是什么样的?
答案 0 :(得分:1)
如果您对单元测试感兴趣,那么模拟数据库是一种好习惯,因此您的测试不依赖于任何类型的IO或数据库。您可能希望隐藏接口后面的DBContext
并使用任何模拟框架(例如Moq)来模拟请求的回调而不是传递连接字符串。
如果您对集成测试感兴趣,那么您只需要单独的数据库,所有代码都可以保持不变。
答案 1 :(得分:0)
为了让你的类很好地进行单元测试,注入所有依赖项是一个很好的做法,这样你就可以独立地测试每个类。
下面尝试这样做 - 它不会开箱即用,因为您需要连接您选择的容器中的依赖项,并且配置可能会有所不同,具体取决于您从哪里获取它但我希望你能得到这个主意。
public DbContext(IConfig config) : base(config.ConnectionString)
{
}
public interface IConfig
{
string ConnectionString {get;}
}
public class RepositoryService : IRepositoryService
{
private readonly DbContext _dbContext;
public RepositoryService(IDbContext dbContext)
{
_dbContext = dbContext;
}
}
public class DtoService : IDtoService
{
private readonly RepositoryService _repository;
public DtoService(IRepositoryService repository)
{
}
}
完成所有这些后,你会使用Dima建议的模拟框架 - 在Rhino中。你可以按照以下方式进行操作:
var config = MockRepository.GenerateStub<IConfig>();
config.Stub(c => c.ConnectionString).Return("yourConnectionString");
var dbContext = MockRepository<IDbContext>();
var controller = new YourController([mockDependency1], [mockDependency2]);
controller.[YourMethod]();
_dbContext.AssertWasCalled(dc => dc.[theMEthodYouExpectToHaveBeenCalled])