C# 单元测试表达式树

C# 单元测试表达式树,c#,linq,unit-testing,testing,lambda,C#,Linq,Unit Testing,Testing,Lambda,我最近需要建立一个表达式树,所以我写了一个测试方法,像这样 /// <summary> /// /// </summary> [TestMethod()] [DeploymentItem("WATrust.Shared.Infrastructure.dll")] public void BuildForeignKeysContainsPredicate_shoud_build_contains_predicate()

我最近需要建立一个表达式树,所以我写了一个测试方法,像这样

    /// <summary>
    /// 
    /// </summary>
    [TestMethod()]
    [DeploymentItem("WATrust.Shared.Infrastructure.dll")]
    public void BuildForeignKeysContainsPredicate_shoud_build_contains_predicate()
    {
        RemoteEntityRefLoader_Accessor<ReferencedEntity> target = CreateRemoteEntityRefLoader_Accessor();

        List<object> foreignKeys = new List<object>() { 1, 2, 3, 4 };
        Expression<Func<ReferencedEntity, bool>> expected = (ReferencedEntity referencedEntity) => foreignKeys.Contains(referencedEntity.Id);
        Expression<Func<ReferencedEntity, bool>> actual;

        actual = target.BuildForeignKeysContainsPredicate(foreignKeys, "Id");

        Assert.AreEqual(expected.ToString(), actual.ToString());
    }
我只是不明白为什么。。。有人对单元测试表达式和如何让我的特定测试通过的建议有一般性的提示吗


谢谢…

根据您发布的代码

  • 预期值是匿名委托/方法。CLR在幕后发挥了一些魔力,动态地添加了一个方法。如果anon.方法使用某些局部变量,CLR将创建一个新类,其中的字段设置为这些值,新的anon方法位于其中(以便该方法可以访问局部变量值)。这就是您的..c_DisplayClass13,编译器的名称很奇怪,这样就不会与用户定义的方法冲突
  • 方法返回的实际值是一个
    表达式
因此。。这两者之间的相等性检查失败。您需要比较两者返回的集合元素。所以我建议。。将预期值和实际值转换为列表(或更好的数据结构),然后调用NUnit的一个获取集合参数的断言

更新:你让我阅读了表达式树+为此,我请客。
我将更改我的答案-通过hack和assert比较表达式树将导致脆弱的测试(例如,如果MS将来更改表达式树的内部结构)

表达式树只是代码块(正如我现在发现的那样),其计算结果与
函数类似。你是说比较每个表达式中的每个节点吗?我喜欢它。。。我同意如果我开始比较一个表达式的各个部分,而微软做了一些改变,我可能会突然遇到很多测试失败的情况。我喜欢你的策略。谢谢
    /// <summary>
    /// 
    /// </summary>
    /// <param name="foreignKeys"></param>
    /// <returns></returns>
    private Expression<Func<TReferencedEntity, bool>> BuildForeignKeysContainsPredicate(List<object> foreignKeys, string primaryKey)
    {
        Expression<Func<TReferencedEntity, bool>> result = default(Expression<Func<TReferencedEntity, bool>>);

        try
        {
            ParameterExpression entityParameter = Expression.Parameter(typeof(TReferencedEntity), "referencedEntity");
            ConstantExpression foreignKeysParameter = Expression.Constant(foreignKeys, typeof(List<object>));
            MemberExpression memberExpression = Expression.Property(entityParameter, primaryKey);
            Expression convertExpression = Expression.Convert(memberExpression, typeof(object));
            MethodCallExpression containsExpression = Expression.Call(foreignKeysParameter
                , "Contains", new Type[] { }, convertExpression);

            result = Expression.Lambda<Func<TReferencedEntity, bool>>(containsExpression, entityParameter);

        }
        catch (Exception ex)
        {
            throw ex;
        }

        return result;
    }
Assert.AreEqual failed.
Expected:<referencedEntity => value(Shared.Infrastructure.Test.RemoteEntityRefLoaderTest+<>c__DisplayClass13).foreignKeys.Contains(Convert(referencedEntity.Id))>.
Actual  :<referencedEntity => value(System.Collections.Generic.List`1[System.Object]                        )            .Contains(Convert(referencedEntity.Id))>.
Assert.AreEqual(expected.Compile().Invoke(inputEntity), 
                actual.Compile().Invoke(inputEntity));