4

私はServiceStackサービスの簡単な単体テストを作成しようとしています。オンラインでテストを行っており、ここではいくつかのスレッドを使用しています。これは、私が達成しようとしているほとんどの詳細を含むメインスレッドです-ServiceStackを使用したHTTPRequestヘッダーの単体テスト

ただし、IDbConnectionオブジェクトをサービスに挿入する際に問題が発生します。webmethodでは、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を作成する必要があります。

4

1 に答える 1

3

調べるオプションがいくつかあると思います。

  • ここここ、または他のさまざまな場所でのモック/スタブ/ユニットテストの拡張方法。これを行うための好ましい方法はないと思いますが、役立つオプションとフレームワーク/ライブラリがいくつかあります。

  • 単体テスト用にSqliteなどのインメモリデータベースを実行します。ここを参照してください。

  • IDConnectionをCustomerLookUpRepositoryに抽象化し、CustomerLookUpRepositoryをサービスに注入することができます。次に、「リポジトリ」をモックすることができます。

私はこの「アレンジメント」を試してみました。これまでのところ、ほとんどの基本的なケースで機能するようです。データアクセスパターンは、RedisWebサービスの例から取っています。ただし、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);
        }
    }
}
于 2013-03-19T22:28:25.193 に答える