单元测试ServiceStack REST webservices

时间:2013-03-26 21:49:45

标签: unit-testing servicestack

我已尝试过几种方法对REST服务进行单元测试,但无济于事。

  1. 关注this帖子,通过创建DirectServiceClient但“方法未实现”引发异常。

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

    _dbConnection = new OrmLiteConnectionFactory(TestConfig.ConnectionString,SqlServerDialect.Provider).OpenDbConnection();

  3. 任何人都可以提供一些关于如何在这种情况下编写单元测试的输入。

    客户服务

    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;
       }
    }
    

    请求

    [Route("/customers")]
    [Route("/customer/{id}")]
    public class CustomerRequest : IReturn<Customer>
    {
        public string id { get; set; }
    }
    

2 个答案:

答案 0 :(得分:3)

  1. 我相信DirectServiceClient更多地用于集成测试(即端到端)。

  2. 使用模拟工具来存根数据库。毕竟,对于此单元测试,您只想测试“任何”方法:

  3. [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));
    }
    

    大概是这样的。 (抱歉abt格式化...... SOO格式化程序没有表现,所以我阻止引用它)

答案 1 :(得分:2)

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

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

下面是通过添加测试'Any_CalledWithAnId_ReturnsCustomer()'来扩展ozczecho答案,并包括所有'仪式'。我确实修改了你提供的代码中的一些内容。我没有为新测试模拟/存根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();
    }
}