您如何表达对作为参数传递的集合的期望?

时间:2013-07-04 23:00:27

标签: c# unit-testing rhino-mocks

我有一个接口方法,其签名如下:

void SetValues(IDictionary<string, object> the_values);

我有一个使用该方法的客户端类。我希望该类的单元测试验证,在特定情况下,传入特定的键和值对。现在,如果我想表达我期望调用SetValues方法使用单键值对{“Date”,DateTime(1972,1,2)}我写下以下内容:

item.Expect(i => i.SetValues(
            Arg<IDictionary<string, object>>.Matches(
                (items) => (items.Count() == 1 &&
                    items.First().Key == "Date" &&
                    (DateTime) items.First().Value == new DateTime(1972,1,2))));

期望似乎有效,但我看起来很难看。是否有更好的方式来表达对作为参数传递的集合内容的期望?

2 个答案:

答案 0 :(得分:1)

很可能没有。我同意这是丑陋的边界线。但更重要的是,它会产生难以理解的异常消息,如下所示:

  

IInterface.SetValues(items =&gt; items.Count()== 1&amp;&amp;                       items.First()。Key ==“Date”&amp;&amp;                       (DateTime)items.First()。Value == new DateTime(1972,1,2));预期#1,实际#0。

是的,你会知道失败了。在2周时间内不是非常有用的信息。说实话,当发生这种情况时,你很可能必须调试它才能知道发生了什么。相反,我建议这样做:

item.Expect(i => i.SetValues(Arg<IDictionary<string, object>>.Is.Anything))
    .WhenCalled(invocation =>
    {
        var items = invocation.Arguments
            .OfType<IDictionary<string, object>>()
            .First();
        Assert.That(items.Count(), Is.EqualTo(1));
        Assert.That(items.First().Key, Is.EqualTo("Date");
        // ...
    });

或者,将验证完全放入其自己的方法中:

item.Expect(i => i.SetValues(IsCalledWithCorrectPair()));

// ... 

private IDictionary<string, object> IsCalledWithCorrectPair()
{
    return Arg<IDictionary<string, object>>.Matches(items =>
    {
        Assert.That(items.Count(), Is.EqualTo(1));
        Assert.That(items.First().Key, Is.EqualTo("Date");
        // ...
        return true;
    });
}

答案 1 :(得分:0)

对于字典中小的固定数量的expecte项目,我认为Count和特定条目的简单检查足够表达。如果值错误,测试将失败...

 items.Count() == 1 && items["Date"]== new DateTime(1972,1,2);

您还可以使用Comparing two collections for equality irrespective of the order of items in them中涵盖的集合比较。