servicestack,Unit Testing,servicestack" /> servicestack,Unit Testing,servicestack" />

Unit testing 单元测试ServiceStack REST Web服务

Unit testing 单元测试ServiceStack REST Web服务,unit-testing,servicestack,Unit Testing,servicestack,我尝试了几种方法对REST服务进行单元测试,但都没有效果 在post之后,创建DirectServiceClient,但引发了“方法未实现”异常 直接实例化web服务并调用Any()方法,它可以工作,但会命中数据库。我已经在设置中初始化了连接,如下所示。但我不知道如何模拟连接对象并在内存中设置客户对象 _dbConnection=new或mliteConnectionFactory(TestConfig.ConnectionString,sqlserverdialent.Provider) 有人

我尝试了几种方法对REST服务进行单元测试,但都没有效果

  • 在post之后,创建DirectServiceClient,但引发了“方法未实现”异常

  • 直接实例化web服务并调用Any()方法,它可以工作,但会命中数据库。我已经在设置中初始化了连接,如下所示。但我不知道如何模拟连接对象并在内存中设置客户对象

    _dbConnection=new或mliteConnectionFactory(TestConfig.ConnectionString,sqlserverdialent.Provider)

  • 有人能提供一些关于如何在这种场景中编写单元测试的信息吗

    客户服务

    public class CustomerService : Service
    {
       private readonly IDbConnection _dbConnection;
    
       public CustomerService(IDbConnection dbConnection)
       {
           _dbConnection = dbConnection;
       }
    
       public object Any(CustomerRequest request)
       {
          if (request.id == null)
          {
              throw new ArgumentException("id is required");
          }
    
          var customer = _dbConnection.QueryDapper<Customer>("getCustomer",new {@id=request.id}).ToList();
    
          return customer;
       }
    }
    
    公共类客户服务:服务
    {
    专用只读IDBConnectionu dbConnection;
    公共客户服务(IDbConnection dbConnection)
    {
    _dbConnection=dbConnection;
    }
    任何公共对象(CustomerRequest请求)
    {
    if(request.id==null)
    {
    抛出新ArgumentException(“需要id”);
    }
    var customer=_dbConnection.QueryDapper(“getCustomer”,new{@id=request.id}).ToList();
    退货客户;
    }
    }
    
    请求

    [Route("/customers")]
    [Route("/customer/{id}")]
    public class CustomerRequest : IReturn<Customer>
    {
        public string id { get; set; }
    }
    
    [路线(“/customers”)]
    [路由(“/customer/{id}”)]
    公共类CustomerRequest:IReturn
    {
    公共字符串id{get;set;}
    }
    
  • 我相信DirectServiceClient更多地用于集成测试(即端到端)

  • 使用模拟工具清除数据库。毕竟,对于这个单元测试,您只想测试“Any”方法:

  • [测试]
    public void Any_调用而没有ID_ExpectThrowArgumentException()
    {
    var db=MockRepository.GenerateStub();
    var request=new CustomerRequest();
    var服务=新客户服务(db);
    抛出(()=>service.Any(请求));
    }
    

    大致就是这样。(很抱歉,abt格式化…SOO格式化程序无法运行,因此我将其引用)

    这是我可以为该方法编写的唯一测试。

    ozczehco的回答将测试引发异常的代码路径。如果要测试通过异常的代码路径,则需要模拟/存根_dbConnection.QueryDapper调用

    下面是ozczecho答案的扩展,添加了一个测试“Any_CalledWithAnId_returnsCastomer()”,包括所有的“仪式”。我确实修改了您提供的代码中的一些内容。我没有为新测试模拟/存根IDbConnection,而是创建了一个InMemoryTestDatabase用于测试不要对您自己的数据库使用此选项,因为它会清除测试的“客户”表

    [TestFixture]
    public class CustomerServiceTest
    {
        public IDbConnectionFactory InMemoryTestDatabase;
    
        [SetUp]
        public void SetUp()
        {
            InMemoryTestDatabase = new OrmLiteConnectionFactory("c:\\testData.db", SqliteDialect.Provider);
        }
    
        [Test]
        public void Any_CalledWithoutId_ExpectThrowArgumentException()
        {
            var db = MockRepository.GenerateStub<IDbConnection>();
            var request = new CustomerRequest();
            var service = new CustomerService(db);
    
            Assert.Throws<ArgumentException>(() => service.Any(request));
        }
    
        [Test]
        public void Any_CalledWithAnId_ReturnsCustomer()
        {
            //Arrange your data
            long requestId;
            using (var con = InMemoryTestDatabase.OpenDbConnection())
            {
                con.CreateTable<Customer>(true); //Force drop to create clean table and data
                con.Insert<Customer>(new Customer { FirstName = "Johnny", LastName = "Test"});
                requestId = con.GetLastInsertId();
            }
    
            //Act
            var request = new CustomerRequest {id = (int)requestId};
            var service = new CustomerService(InMemoryTestDatabase.OpenDbConnection());
            var result = (Customer)service.Any(request);
    
            //Assert
            Assert.AreEqual(requestId, result.Id);
            Assert.AreEqual("Johnny", result.FirstName);
        }
    }
    
    
    [Route("/customers")]
    [Route("/customer/{id}")]
    public class CustomerRequest : IReturn<Customer>
    {
        public long id { get; set; }
    }
    
    public class Customer
    {
        [AutoIncrement]
        public long Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    
    public class CustomerService : ServiceStack.ServiceInterface.Service
    {
        private readonly IDbConnection _dbConnection;
    
        public CustomerService(IDbConnection dbConnection)
        {
            _dbConnection = dbConnection;
        }
    
        public object Any(CustomerRequest request)
        {
            if (request.id == null)
            {
                throw new ArgumentException("id is required");
            }
    
            var customer = _dbConnection.QueryDapper<Customer>("Select * From Customer Where Id = @id", new { id = request.id }).ToList();
    
            return customer.FirstOrDefault();
        }
    }
    
    [TestFixture]
    公共类CustomerServiceTest
    {
    MemoryTestDatabase中的公共IDbConnectionFactory;
    [设置]
    公共作废设置()
    {
    InMemoryTestDatabase=new或mliteConnectionFactory(“c:\\testData.db”,sqlitedialent.Provider);
    }
    [测试]
    public void Any_调用而没有ID_ExpectThrowArgumentException()
    {
    var db=MockRepository.GenerateStub();
    var request=new CustomerRequest();
    var服务=新客户服务(db);
    抛出(()=>service.Any(请求));
    }
    [测试]
    public void Any_CalledWithAnId_ReturnsCustomer()
    {
    //整理数据
    长请求ID;
    使用(var con=InMemoryTestDatabase.OpenDbConnection())
    {
    con.CreateTable(true);//强制拖放以创建干净的表和数据
    con.Insert(新客户{FirstName=“Johnny”,LastName=“Test”});
    requestId=con.GetLastInsertId();
    }
    //表演
    var request=newcustomerrequest{id=(int)requestId};
    var service=newcustomerservice(InMemoryTestDatabase.OpenDbConnection());
    var结果=(客户)服务。任何(请求);
    //断言
    arenequal(requestId,result.Id);
    Assert.AreEqual(“Johnny”,result.FirstName);
    }
    }
    [路线(“/客户”)]
    [路由(“/customer/{id}”)]
    公共类CustomerRequest:IReturn
    {
    公共长id{get;set;}
    }
    公共类客户
    {
    [自动增量]
    公共长Id{get;set;}
    公共字符串名{get;set;}
    公共字符串LastName{get;set;}
    }
    公共类CustomerService:ServiceStack.ServiceInterface.Service
    {
    专用只读IDBConnectionu dbConnection;
    公共客户服务(IDbConnection dbConnection)
    {
    _dbConnection=dbConnection;
    }
    任何公共对象(CustomerRequest请求)
    {
    if(request.id==null)
    {
    抛出新ArgumentException(“需要id”);
    }
    var customer=_dbConnection.QueryDapper(“Select*From customer,其中Id=@Id”,new{Id=request.Id})。ToList();
    返回customer.FirstOrDefault();
    }
    }
    
    这是我能为这种方法编写的唯一测试。很抱歉,我不熟悉TDD,也不知道如何检查属性是否正确映射到CustomerTo。我的意思是如何模拟数据库中的数据。谢谢你的回答!我正在调用不同数据库中的存储过程来填充DTO,所以如何使用内存中的数据库执行此操作。我不知道hink Sqlite支持存储过程-。您可以创建一个仅用于测试的数据库,而不是内存中的数据库。
    [TestFixture]
    public class CustomerServiceTest
    {
        public IDbConnectionFactory InMemoryTestDatabase;
    
        [SetUp]
        public void SetUp()
        {
            InMemoryTestDatabase = new OrmLiteConnectionFactory("c:\\testData.db", SqliteDialect.Provider);
        }
    
        [Test]
        public void Any_CalledWithoutId_ExpectThrowArgumentException()
        {
            var db = MockRepository.GenerateStub<IDbConnection>();
            var request = new CustomerRequest();
            var service = new CustomerService(db);
    
            Assert.Throws<ArgumentException>(() => service.Any(request));
        }
    
        [Test]
        public void Any_CalledWithAnId_ReturnsCustomer()
        {
            //Arrange your data
            long requestId;
            using (var con = InMemoryTestDatabase.OpenDbConnection())
            {
                con.CreateTable<Customer>(true); //Force drop to create clean table and data
                con.Insert<Customer>(new Customer { FirstName = "Johnny", LastName = "Test"});
                requestId = con.GetLastInsertId();
            }
    
            //Act
            var request = new CustomerRequest {id = (int)requestId};
            var service = new CustomerService(InMemoryTestDatabase.OpenDbConnection());
            var result = (Customer)service.Any(request);
    
            //Assert
            Assert.AreEqual(requestId, result.Id);
            Assert.AreEqual("Johnny", result.FirstName);
        }
    }
    
    
    [Route("/customers")]
    [Route("/customer/{id}")]
    public class CustomerRequest : IReturn<Customer>
    {
        public long id { get; set; }
    }
    
    public class Customer
    {
        [AutoIncrement]
        public long Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    
    public class CustomerService : ServiceStack.ServiceInterface.Service
    {
        private readonly IDbConnection _dbConnection;
    
        public CustomerService(IDbConnection dbConnection)
        {
            _dbConnection = dbConnection;
        }
    
        public object Any(CustomerRequest request)
        {
            if (request.id == null)
            {
                throw new ArgumentException("id is required");
            }
    
            var customer = _dbConnection.QueryDapper<Customer>("Select * From Customer Where Id = @id", new { id = request.id }).ToList();
    
            return customer.FirstOrDefault();
        }
    }