1

テストで 2 つの Linq 式をアサートしようとしています。私は Moq を使用しており、テスト中のメソッド内で呼び出された式をコールバックでキャプチャします。

Expression<Func<Role, bool>> actualExpression = null;
roleRepositoryMock.Setup(t => t.Search(It.IsAny<Expression<Func<Role, bool>>>()))
            .Callback((Expression<Func<Role, bool>> exp) =>
                {
                    actualExpression = exp;
                })
            .Returns(new List<Role> { new Role { Name = "site1_code_role1", Description = "descr" }, new Role { Name = "site1_code" } });

次に、これを次の方法で比較します。

var siteCode = "site1";
var namePattern = "role1";
Expression<Func<Role, bool>> expectedExpression = 
                    t => (string.IsNullOrEmpty(siteCode)
                          || t.Name.StartsWith(siteCode + "_") 
                          || t.Name == siteCode) 
                          && t.Name.Contains(namePattern);
Assert.AreEqual(expectedExpression.ToString(), actualExpression.ToString());

上記の Assert は失敗します。文字列に期待される式は次のとおりです:

t => (((IsNullOrEmpty(value(BL.Tests.RolesServiceTests+<>c__DisplayClass6).siteCode) OrElse t.Name.StartsWith((value(BL.Tests.RolesServiceTests+<>c__DisplayClass6).siteCode + "_"))) OrElse (t.Name == value(BL.Tests.RolesServiceTests+<>c__DisplayClass6).siteCode)) AndAlso t.Name.Contains(value(BL.Tests.RolesServiceTests+<>c__DisplayClass6).namePattern))

実際の式は次のようになります。

t => (((IsNullOrEmpty(value(BL.Services.RolesService+<>c__DisplayClass3).site) OrElse t.Name.StartsWith((value(BL.Services.RolesService+<>c__DisplayClass3).site + "_"))) OrElse (t.Name == value(BL.Services.RolesService+<>c__DisplayClass3).site)) AndAlso t.Name.Contains(value(BL.Services.RolesService+<>c__DisplayClass3).pattern))

違いは次のとおりです。

  • c_DisplayClass6およびc_DisplayClass3
  • BL.Services.RolesService および BL.Tests.RolesServiceTests (名前空間が異なります)

それを解決する理由と方法について、誰かが説明したり、正しい方向に送ってくれたりできますか? ToString() を介してこれらを比較しようとするのは、まったく間違った方法でしょうか? 代替案?

4

1 に答える 1

0

実装の詳細に結び付けられることなく、コード片の外部から観察可能な動作を検証するテストを作成することをお勧めします。式を文字列に変換することで、テストを正確な式だけでなくToString、将来の .NET バージョンで変更される可能性があるメソッドの実装にも結び付けます。

より良いアプローチは、何らかの出力状態でアサートすることです。リポジトリに渡された linq 式が正しいRoleコレクションを除外することを確認したいようです。コールバックを介して既に式をキャプチャできるので、この式に対していくつかのテストを作成してみませんか?

RolePOCOであると仮定すると、Role入力のさまざまなコレクションで式を呼び出し、正しい出力が生成されることをアサートするテストを作成するのは簡単です。式が複雑な場合、多くの入力が必要になる場合がありますが、次のようになります。

var roles = new List<Role>
{
    new Role { Name = siteCode+"_role1"  },
    new Role { Name = siteCode+"_role22"  },
    new Role { Name = siteCode+"_role1324"  },
};

Assert.AreEqual(2, roles.Where(actualExpression.Compile()).Count()); //test the number of roles returned is as expected

さらに良いのは、クライアント コードのインターフェイスでのみテストし、リポジトリがどのようにクエリされるかをテストで知らずにテストすることです。

于 2013-04-06T12:11:19.910 に答える