繁体   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