【问题标题】:How to assert an IEnumerable parameter where order is unimportant?如何在顺序不重要的情况下断言 IEnumerable 参数?
【发布时间】:2014-02-03 11:44:12
【问题描述】:

我正在编写单元测试,我想确保使用一些参数调用特定方法:

var myMock = MockRepository.GenerateMock<IMyService>();

IMyService 上有一个带有签名的方法

public bool SomeMethod(IEnumerable<string> values)

我有一个使用我的模拟的业务逻辑层

public class BusinessLogic
{
  protected MyMock MyMock{get;set;}

  public BusinessLogic (myMock)
  {
    this.MyMock = myMock;
  }

  public bool DoLogic()
  {
    var myCollection = // loaded from somewhere
    return this.MyMock(myCollection);
  }
}

我想通过确保正确调用 SomeMethod 来测试 DoLogic 方法。但是我无法控制(并且真的不希望它控制集合的顺序)。

我想断言 SomeMethod 方法是使用 IEnumerable {"a", "b", "c"} 调用的,但我不在乎顺序。

目前为止

myMock.Expect(x => x.MyMethod(new string[]{"a", "b", "c"});

myMock.AssertWasCalled(x => x.MyMethod(new string[]{"a", "b", "c"});

但是如果用{"b", "a", "c"} 调用它会失败。我不想更改我的业务逻辑以确保参数的顺序(因为这会围绕测试设计 BLL)。

如何断言这个方法调用?

【问题讨论】:

  • 为了测试目的,你测试它的顺序并不重要,所以只需 ExpectAssert 以相同的顺序。
  • @AdamHouldsworth 但如果我的 BLL 以不同的顺序通过集合,它不会通过测试吗?
  • 据我所见,您正在模拟通话,因此您可以控制订单...除非我错过了问题中的某些内容。我的评论是基于您控制输入以及对输出的期望这一事实。如果您不控制输入,那么我的评论是没有意义的。抱歉,那部分我不是很清楚。
  • @AdamHouldsworth 感谢您的帮助,我已尝试扩展以准确显示我要测试的课程

标签: c# unit-testing rhino-mocks


【解决方案1】:

你可以使用Arg&lt;T&gt;.Matches:

myMock.Expect(x => x.MyMethod(Arg<IEnumerable<string>>.Matches(s => !s.Except(expected).Any() && !expected.Except(s).Any()));

【讨论】:

  • 或者expected.All(e =&gt; calledWith.Contains(e)),如果您不想重复检查计数。
【解决方案2】:

测试框架通常有这种匹配的断言,你可以混合使用这两个。以 NUnit 的 EquivalentTo 为例:

myMock.Expect(x => x.MyMethod(Arg<IEnumerable<string>>.Matches(value => 
{
    Assert.That(value, Is.EquivalentTo(new[] { "c", "b", "a" }));
    return true;
}));

这样,生成的错误信息应该比 Rhino 生成的信息更具描述性。

【讨论】:

  • 这实际上不会编译。 Matches 采用表达式树,而不是委托。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-13
  • 2010-11-25
  • 2021-05-12
  • 1970-01-01
  • 2021-10-17
  • 2021-02-25
相关资源
最近更新 更多