Asp.net mvc 3 如何测试WebAPI控制器?

Asp.net mvc 3 如何测试WebAPI控制器?,asp.net-mvc-3,asp.net-web-api,Asp.net Mvc 3,Asp.net Web Api,我有一个webAPI应用程序,它有一个存储库层、DTO服务层和webAPI层。WebAPI调用DTO调用存储库 我的存储库是这样开始的: public class RepositoryService : IRepositoryService { private readonly DbContext _db; public RepositoryService(string connectionString) { _d

我有一个webAPI应用程序,它有一个存储库层、DTO服务层和webAPI层。WebAPI调用DTO调用存储库

我的存储库是这样开始的:

public class RepositoryService : IRepositoryService
    {
        private readonly DbContext _db;

        public RepositoryService(string connectionString)
        {
            _db = new DbContext(connectionString);
        }

        public RepositoryService()
        {
            _db = new DbContext();
        }
public class DtoService : IDtoService
    {
        private readonly RepositoryService _repository;

        public DtoService(string connectionString)
        {
            _repository = new RepositoryService(connectionString);  
        }

        public DtoService()
        {
            _repository = new RepositoryService();   
        }
public DbContext() : base("name=TestConnection")
        {

        }

public DbContext(string connectionString) : base(connectionString)
        {

        }
我的DTO服务是这样开始的:

public class RepositoryService : IRepositoryService
    {
        private readonly DbContext _db;

        public RepositoryService(string connectionString)
        {
            _db = new DbContext(connectionString);
        }

        public RepositoryService()
        {
            _db = new DbContext();
        }
public class DtoService : IDtoService
    {
        private readonly RepositoryService _repository;

        public DtoService(string connectionString)
        {
            _repository = new RepositoryService(connectionString);  
        }

        public DtoService()
        {
            _repository = new RepositoryService();   
        }
public DbContext() : base("name=TestConnection")
        {

        }

public DbContext(string connectionString) : base(connectionString)
        {

        }
我的DbContext如下所示:

public class RepositoryService : IRepositoryService
    {
        private readonly DbContext _db;

        public RepositoryService(string connectionString)
        {
            _db = new DbContext(connectionString);
        }

        public RepositoryService()
        {
            _db = new DbContext();
        }
public class DtoService : IDtoService
    {
        private readonly RepositoryService _repository;

        public DtoService(string connectionString)
        {
            _repository = new RepositoryService(connectionString);  
        }

        public DtoService()
        {
            _repository = new RepositoryService();   
        }
public DbContext() : base("name=TestConnection")
        {

        }

public DbContext(string connectionString) : base(connectionString)
        {

        }
到目前为止,这允许我有选择地定义在运行应用程序进行测试时使用的连接字符串

第一个问题:这种方法看起来合适吗

现在我已经到了WebAPI层,我不再只有一个控制器类。我有很多不同的控制器。我正在考虑为每个控制器使用并实现这些构造函数,但必须有更好的方法来实现这一点。有些东西告诉我这就是依赖注入发挥作用的地方,但我不确定

我可以这样做:

public class RepositoryService : IRepositoryService
    {
        private readonly DbContext _db;

        public RepositoryService(string connectionString)
        {
            _db = new DbContext(connectionString);
        }

        public RepositoryService()
        {
            _db = new DbContext();
        }
public class DtoService : IDtoService
    {
        private readonly RepositoryService _repository;

        public DtoService(string connectionString)
        {
            _repository = new RepositoryService(connectionString);  
        }

        public DtoService()
        {
            _repository = new RepositoryService();   
        }
public DbContext() : base("name=TestConnection")
        {

        }

public DbContext(string connectionString) : base(connectionString)
        {

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

    var accountController=新accountController(connectionStringForTesting)

  • 但我知道这不实际,所以


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

    如果您对单元测试感兴趣,那么最好模拟数据库,这样您的测试就不会依赖于任何类型的IO或数据库。您可能希望将
    DBContext
    隐藏在接口后面,并使用任何模拟框架(例如)来模拟请求的回调,而不是传递连接字符串


    如果您对集成测试感兴趣,那么您只需要单独的数据库,所有代码都可以保持不变。

    为了使您的类能够很好地进行单元测试,最好插入所有依赖项,以便您可以单独测试每个类

    下面是一个尝试——它不会开箱即用,因为您需要将依赖项连接到您选择的容器中,配置可能会有所不同,这取决于您从何处获得它,但我希望您能理解

     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)
            {
            }
    }
    
    完成所有这些之后,您将使用Rhino.Mocks中Dima-in建议的模拟框架。模拟您将遵循以下思路:

    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])
    
    var config=MockRepository.GenerateStub();
    config.Stub(c=>c.ConnectionString).Return(“yourConnectionString”);
    var dbContext=MockRepository();
    var控制器=新的YourController([mockDependency1],[mockDependency2]);
    控制器。[方法]();
    _调用dbContext.assertwas(dc=>dc.[TheMethodYouExpecttoHaveCalled])