如何测试Web API控制器?

时间:2013-05-06 00:01:11

标签: asp.net-mvc-3 asp.net-web-api

我有一个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层,我不仅仅有一个控制器类。我有一堆不同的控制器。我正在考虑为每个控制器完成并实现这些构造函数,但是必须有更好的方法来实现这一点。有些东西告诉我这是依赖注入发挥作用的地方,但我不确定。

我可以这样做:

  1. 为每个控制器创建构造函数,就像我上面的服务一样
  2. 在我的测试中,新建了每个控制器的实例,如

    var accountController = new AccountController(connectionStringForTesting)

  3. 但我知道这不实用,所以......

    第二个问题:实用的方法是什么样的?

2 个答案:

答案 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])