簡體   English   中英

ServiceStack服務的單元測試

[英]Unit tests for ServiceStack services

我正在嘗試為ServiceStack服務編寫簡單的單元測試,我正在通過測試他們在線和幾個線程。 這是我想要完成的大部分細節的主線程 - 使用ServiceStack進行單元測試HTTPRequest標頭

但是,我遇到了將IDbConnection對象注入服務的問題。 在web方法中,使用OrmLite的GetDictionary方法填充字典對象。 但是我無法模仿它,因為GetDictionary是擴展方法。

 private Mock<IDbConnection> _dbConnectionMock;
 private Dictionary<string, string> _nameValuePairs;

 [SetUp]
 public void SetUp()
 {
    _dbConnectionMock = new Mock<IDbConnection>();

    _nameValuePairs = new Dictionary<string, string>()
    {
            {"name","test"},
            {"Updatedby",   "5/23/12 7:00:15 AM"},
            {"Address", "212 Adam St."}
    };
}

在測試方法

 var service = new CustomerLookupService(_dbConnectionMock.Object);
 var response = (HttpResult)service.Any(new CustomerLookup { name = "test" });
 //assert statements

如果無法模擬GetDictionary方法,我甚至願意調用命中DB的web方法,為此我需要創建AppHost。

我認為有幾個選項可供研究。

  • 模擬/存根/單元測試擴展方法在這里這里或其他各種點。 我不認為有一種首選方法可以做到這一點,但有一些選項和框架/庫可以提供幫助。

  • 運行內存數據庫(如Sqlite)進行單元測試。 看到這里

  • 您可以將IDConnection抽象為CustomerLookUpRepository,並將CustomerLookUpRepository注入您的服務。 然后你可以模擬你的'存儲庫'。

我試試這個'安排'。 到目前為止,它似乎適用於大多數基本情況。 數據訪問模式來自Redis Web Service示例 但是YMMV。

測試 (使用RhinoMocks)

    public void SomeTest()
    {
        var _nameValuePairs = new Dictionary<string, string>()
        {
            {"name","test"},
            {"Updatedby",   "5/23/12 7:00:15 AM"},
            {"Address", "212 Adam St."}
        };

        var mockSqlRepository = MockRepository.GenerateMock<ISqlRepository>();
        mockSqlRepository.Stub(
            x => x.Exec(Arg<Func<IDbConnection, Dictionary<string, string>>>.Is.NotNull)).Return(_nameValuePairs);

        var service = new CustomerLookupService { SqlRepository = mockSqlRepository }
        //MORE TEST CODE...  
    }

服務類 - 使用ISqlRepository抽象/隱藏IDbConnection。 ISqlRepository有一個函數,它將函數作為參數。 函數簽名(參數)將IDbConnection作為參數,因此我不必編寫幾種方法來訪問數據庫。

public class CustomerLookupService
{
    public ISqlRepository SqlRepository { get; set; }

    public void Any(CustomerLookup request)
    {
        var results =
            SqlExec<Dictionary<string, string>>((con) => con.GetDictionary<type, type>("Select id, name from table"));
        //MORE SERVICE CODE
    }

    public T SqlExec<T>(Func<IDbConnection, T> fn)
    {
        return SqlRepository.Exec(fn);
    }
}

ISqlRepository

public interface ISqlRepository
{
    T Exec<T>(Func<IDbConnection, T> fn);
}

SqlRepository

public class SqlRepository : ISqlRepository
{
    public IDbConnectionFactory DbFactory { get; set; }

    public T Exec<T>(Func<IDbConnection, T> fn)
    {
        using (var con = DbFactory.OpenDbConnection())
        {
            return fn(con);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM