2013-03-26 105 views
2

我試過幾種方法來單元測試REST服務,但無濟於事。單元測試ServiceStack REST webservices

  1. 其次this後,通過創建DirectServiceClient但「方法未實現」異常。

  2. 直接實例化Web服務並調用Any()方法,它工作但它擊中了數據庫。我已經在設置中初始化了連接,如下所示。但我不知道如何模擬連接對象並設置內存中的客戶對象。

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

任何人都可以提供一些關於如何在這種情況下編寫單元測試的輸入。

客服

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

這是我可以爲此方法編寫的唯一測試。

ozczehco的答案將測試拋出異常的代碼路徑。如果你想測試通過異常的代碼路徑,你需要模擬/存根_dbConnection.QueryDapper調用。

下面通過添加一個測試'Any_CalledWithAnId_ReturnsCustomer()'在ozczecho答案擴展,幷包括所有'儀式'。我在你提供的代碼中修改了一些東西。我沒有爲新測試模擬/存根IDbConnection,而是創建了一個用於測試的InMemoryTestDatabase。 DON「T使用本對自己DATBASE,因爲它抹布用於測試的‘客戶’表。

[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(); 
    } 
} 
+0

感謝您的回覆!我打電話給存儲過程在不同的數據庫中填充DTO的,所以如何在內存數據庫中做到這一點 – Sunny 2013-03-28 00:25:19

+0

我不認爲Sqlite支持存儲過程 - http://stackoverflow.com/questions/3335162/creating-stored-procedure-and-sqlite。而不是一個In-內存數據庫,你可以創建一個數據庫只用於測試。 – paaschpa 2013-03-28 03:17:00

3
  1. 我相信DirectServiceClient更多的是用於集成測試(即端對端)。

  2. 使用模擬工具來存根數據庫。畢竟,對於這個單元測試你只是想測試「任何」方法:

[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格式化程序不行爲,所以我阻止引用它)

+0

這是唯一的測試,我可以爲這個方法寫的。我很抱歉,我是新來的TDD,以及如何檢查屬性是否正確映射到客戶端。我的意思是如何從數據庫模擬數據。 – Sunny 2013-03-26 22:52:07

+0

謝謝!它幫助.. – Sunny 2013-03-28 03:47:07