簡體   English   中英

Assert.That() 不評估給定的約束

[英]Assert.That() does not evaluate given constraint

我有一個字符串值列表。 我用 foreach 迭代這個列表。 我申請了每個列表項 Assert.That() 方法。 現在來個轉折:我給出了一個返回 IResolveConstraint 的函數作為該方法的第二個參數。 當函數返回Has.Exactly(1).Contains()然后在列表的第二項( foreach 的第二次迭代)處,斷言評估(拋出)此消息:“預期:包含“值”的集合”。 但是斷言應該通過,因為它正在驗證一個項目,而不是一個集合。

我有 NUnit 3.2.1。 我升級到 3.12.0 版,之后消息從:“預期:包含“值”的集合”更改為消息:“預期:某些項目等於“值””並且斷言仍然沒有通過。


public class Verifiers
{
public void VerifyCollectedValues(List<string> collectedValues, List<string> expectedValues
, string collectedValuesFrom, int countOfValueExpactance, bool verifyExactSameValue = true)
        {
// Create a constraint function
            Func<string, IResolveConstraint> constraintFunction = CreateConstraintFunction(Has.Exactly(countOfValueExpactance), verifyExactSameValue);

// Pass the constraint to the method
            VerifyCollectedValues(constraintFunction, collectedValues, expectedValues, collectedValuesFrom);
        }

public void VerifyCollectedValues(Func<string, IResolveConstraint> constraintFunction, List<string> collectedValues, List<string> expectedValues
, string collectedValuesFrom)
        {
            foreach (string expectedValue in expectedValues)
            {
// Apply the constraint
                Assert.That(collectedValues, constraintFunction(expectedValue));             
            }
        }

public Func<string, IResolveConstraint> CreateConstraintFunction(ConstraintExpression constraintExpression, bool verifyExactSameValue)
        {
            if (verifyExactSameValue)
            {
                return (string value) => constraintExpression.EqualTo(value);
            }
            else
            {              
                return (string value) => constraintExpression.Contains(value);
            }
        }
}

示例代碼:


            Verifiers verifiers = new Verifiers(); 

            List<string> expectedValues = new List<string>()
            {
                "value1",
                "value2",
                "value3",                
            };
            var collectedValues = new List<string>()
            {
                "some_value0",
                "some_value1",
                "some_value2",
                "some_value3",
            };
// This passes
            foreach(string expectedValue in expectedValues)
            {
                Assert.That(collectedValues, Has.Exactly(1).Contains(expectedValue));
            }

// This fails with the message: "Expected: collection containing "value2"" (with NUnit v3.2.1) / "Expected: some item equal to "value2""(with NUnit v3.12.0)
            verifiers.VerifyCollectedValues(collectedValues, expectedValues, 1, false);

我的假設是 IResolveConstraint 導致了這個問題。 我不明白的是為什么列表的第一項通過但第二項沒有通過。

我將不勝感激任何答案。

更新:

我已經做了一些編輯,並在此基礎上排除了 IResolveConstraint 導致問題的可能性。 這是當前代碼的示例:


public class Verifiers
 {
        public void VerifyCollectedValues(List<string> collectedValues, List<string> expectedValues, string collectedValuesFrom, int countOfValueExpectance, bool verifyExactSameValue = true)
        {            
            VerifyCollectedValues(CreateConstraintExpressionExactly(countOfValueExpectance), collectedValues, expectedValues, collectedValuesFrom, verifyExactSameValue);
        }

        private void VerifyCollectedValues(ConstraintExpression constraintExpression, List<string> collectedValues, List<string> expectedValues, string collectedValuesFrom, bool exactSameValue)
        {
            if (exactSameValue)
            {
                VerifyCollectedValuesEqualTo(constraintExpression, collectedValues, expectedValues, collectedValuesFrom);
            }
            else
            {
                VerifyCollectedValuesContains(constraintExpression, collectedValues, expectedValues, collectedValuesFrom);
            }
        }

        private void VerifyCollectedValuesEqualTo(ConstraintExpression constraintExpression, List<string> collectedValues, List<string> expectedValues, string collectedValuesFrom)
        {
            Func<string, EqualConstraint> constraintFunction = (string value) => constraintExpression.EqualTo(value);
            foreach (string expectedValue in expectedValues)
            {
                Assert.That(collectedValues, constraintFunction(expectedValue));
            }
        }

        private void VerifyCollectedValuesContains(ConstraintExpression constraintExpression, List<string> collectedValues, List<string> expectedValues, string collectedValuesFrom)
        {
            // if I don't use constraintExpression but write the expression manually (Has.Exactly(1).Contains(value)), then it works just fine
            Func<string, ContainsConstraint> constraintFunction = (string value) => constraintExpression.Contains(value);
            foreach (string expectedValue in expectedValues)
            {
                Assert.That(collectedValues, constraintFunction(expectedValue));
            }
        }

        private ConstraintExpression CreateConstraintExpressionExactly(int countOfExpectance)
        {
            return Has.Exactly(countOfExpectance);
        }
            var verifiers = new Verifiers();

            List<string> expectedValues = new List<string>()
            {                
                "value1",
                "value2",
                "value3",                
            };
            var collectedValues = new List<string>()
            {
                "some_value0",
                "some_value1",
                "some_value2",
                "some_value3",
            };
            // This one pass successfully
            foreach(string expectedValue in expectedValues)
            {
                Assert.That(collectedValues, Has.Exactly(1).Contains(expectedValue));
            }
            // But this one still doesn't pass and fails at the second list item "value2"
            verifiers.VerifyCollectedValues(collectedValues, expectedValues, "list of strings", 1, false);

如果實際值為非集合,您認為Has.Exactly(1).EqualTo()將通過的假設是不正確的。 如果傳遞非集合類型, ExactCountConstraint將出錯(與失敗不完全相同)。

但是,在這種情況下, string字符的集合,因此它會嘗試運行。

問題是您正在使用集合約束,它迭代列表,但您自己也在迭代它。 你要么自己做這一切(這看起來很傻),要么依靠ExactCountConstraint to do the work

如果您繼續自己迭代列表,則不應使用任何集合約束。 在示例情況下,您只需使用Is.EqualTo()

好吧,錯誤實際上在您的實現中,因為您一直在傳遞 ConstraintExpression。 如果您嘗試分解工作代碼並為每個驗證創建方法,您將得到如下內容:

[Test]
public void ListCompareTest()
{
    List<string> expectedValues = new List<string>()
    {
        "value1",
        "value2",
        "value3",
    };
    var collectedValues = new List<string>()
    {
        "some_value0",
        "some_value1",
        "some_value2",
        "some_value3",
    };
    int count = 1;
    // This one pass successfully
    foreach (string expectedValue in expectedValues)
    {
        ItemsConstraintExpression itemsConstraintExpression = GetExactly(count);
        // this code works
        Assert.That(collectedValues, GetContains(expectedValue, itemsConstraintExpression));
    }
    // this code works as well
    DoVerification(expectedValues, collectedValues, 1, false);
}

public static void DoVerification(List<string> expectedList, List<string> actualList, int exactlyCount, bool equalsOrContains)
{
    if (equalsOrContains)
    {
        foreach (var expectedValue in expectedList)
        {
            Assert.That(actualList, GetEquals(expectedValue, GetExactly(exactlyCount)));
        }
    }
    else
    {
        foreach (var expectedValue in expectedList)
        {
            Assert.That(actualList, GetContains(expectedValue, GetExactly(exactlyCount)));
        }
    }
}

private static EqualConstraint GetEquals(string expectedValue, ItemsConstraintExpression itemsConstraintExpression)
{
    return itemsConstraintExpression.EqualTo(expectedValue);
}

private static ContainsConstraint GetContains(string expectedValue, ItemsConstraintExpression itemsConstraintExpression)
{
    return itemsConstraintExpression.Contains(expectedValue);
}

private static ItemsConstraintExpression GetExactly(int count)
{
    return Has.Exactly(count);
}

暫無
暫無

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

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