Frage

Ich brauche vor kurzem einen Ausdrucksbaum zu bauen, so schrieb ich eine Testmethode, wie so ...

    /// <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());
    }

Als ich endlich die „BuildForeignKeysContainsPredicate“ Methode Arbeits ich nie teh Test zu bestehen bekommen konnte ... Hier ist die Methode:

    /// <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;
    }

Aber der Test nicht jedes Mal, schaltete ich die Linie Assert.AreEqual(expected, actual); zu diesem. Assert.AreEqual(expected.ToString(), actual.ToString()); ich, warum es verstehen, versagt, weil, wenn man sich die Ergebnisse der ToString-Methode sehen sie anders sind

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))>.

Ich verstehe einfach nicht, warum ... Hat jemand haben allgemeine Tipps auf Unit-Tests Ausdrücke und Vorschlägen, wie mein spezieller Test erhalten passieren?

Danke ...

War es hilfreich?

Lösung

Basierend auf den Code, den Sie geschrieben haben,

  • der erwartete Wert ist eine anonyme Delegat / Methode. Die CLR tut etwas Magie hinter den Kulissen ein Verfahren im laufenden Betrieb hinzuzufügen. Im Falle der Anon. Verfahren verwenden bestimmte lokale Variablen, die CLR eine neue Klasse erstellt mit Feldern auf diese Wert mit der neuen anon Methode darin (so dass das Verfahren der lokalen Variablen Werte zugreifen kann). Also das ist Ihr ..c_DisplayClass13, mit einem Compiler seltsame Namen gegeben, so dass es nicht mit benutzerdefinierten kollidiert Methoden.
  • Der tatsächliche Wert von Ihrer Methode zurückgegeben wird, ist ein Expression<T>.

Und damit .. die Gleichheitsprüfung zwischen diesen beiden ausfällt. Sie müssen die Elemente der Auflistung von beiden zurück vergleichen. So würde ich vorschlagen .. konvertieren sowohl die erwarteten und tatsächlichen Werte Listen (oder eine bessere Datenstruktur) und rufen Sie dann eine der NUnit der behauptet, dass Take Erfassungsparameter.

Aktualisieren : Du hast mich auf Expression Trees zu lesen. +1 dafür.
Ich werde meine Antwort ändern - die Expression Bäume über Hack-and-Assertion Vergleich würde zu einem fragilen Test führt (zum Beispiel, wenn MS die innere Struktur eines Ausdruck Baum in der Zukunft ändert)
Expression Bäume sind nur Codeblocks (wie ich jetzt herausgefunden), die ähnlich wie bei einem Func<TInput,TResult) zu einem Ergebnis zu bewerten - so mein Test den erwarteten und tatsächlichen Codeblöcken den gleichen Eingang und sehen, ob sie die gleiche Leistung liefern zu geben wäre.  Also meine assert für Ihren Test wäre

Assert.AreEqual(expected.Compile().Invoke(inputEntity), 
                actual.Compile().Invoke(inputEntity));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top