【问题标题】:Rhino Mocks Error: Previous method 'IEnumerator.MoveNext();' requires a return value or an exception to throwRhino Mocks 错误:以前的方法 'IEnumerator.MoveNext();'需要返回值或抛出异常
【发布时间】:2011-09-10 22:05:52
【问题描述】:

我有以下测试代码:

parentViewModel = MockRepository.GenerateMock<IParentViewModel>();
parentViewModel.Expect(x => x.GetPropertyValue<IEnumerable<Milestone>>("JobMilestones")).Return(new Milestone[0]);

viewModel = new JobPenaltiesViewModel(j, new Penalty[0], _opContext, parentViewModel);

Assert.That(viewModel.Milestones.Count(), Is.EqualTo(0));
parentViewModel.VerifyAllExpectations();

List<string> propsChanged = new List<string>();
viewModel.PropertyChanged += (s, e) => propsChanged.Add(e.PropertyName);

parentViewModel.Raise(x => x.PropertyChanged += null, parentViewModel, new PropertyChangedEventArgs("JobMilestones"));

AssertPropertiesChangedAsExepected(propsChanged, 1, "Milestones");

Milestone m1 = GenerateMilestone(j);
List<Milestone> milestones1 = new List<Milestone> { m1 };
parentViewModel.Expect(x => x.GetPropertyValue<IEnumerable<Milestone>>("JobMilestones")).Return(milestones1).Repeat.Any();

IEnumerable<Milestone> milestones = viewModel.Milestones;
Assert.That(milestones.Count(), Is.EqualTo(1));
parentViewModel.VerifyAllExpectations();

所有测试和断言都成功,直到:

Assert.That(milestones.Count(), Is.EqualTo(1));

这就是我得到异常的地方:

Previous method 'IEnumerator.MoveNext();' requires a return value or an exception to throw.

我已经尝试了我能想到的一切,我的测试似乎表明 parentViewModel Mock 返回 null 或空枚举(即,当我使用调试器检查返回的值时,“结果视图”表示枚举没有返回结果)。

我在这里错过了什么?

【问题讨论】:

  • 如果你尝试做:IEnumerable&lt;Milestone&gt; milestones = parentViewModel.Milestones;Assert.That(milestones.Count(), Is.EqualTo(1)),你会得到正确的结果吗? (只需验证您松开 m1 的位置)
  • 不,Assert.That(milestones.Count(), Is.EqualTo(1)) 是异常的来源。我从来没有到过parentViewModel.VerifyAllExpectations()
  • 好吧,我不是很清楚我的意思。我的意思是在parentViewModel.Expect(x =&gt; x.GetPropertyValue&lt;IEnumerable&lt;Milestone&gt;&gt;("JobMilestones")).Return(milestones1).Repeat.Any(); 之后添加这些行,这样你就可以在parentViewModel 上断言,然后再在viewModel 上断言。验证 m1 是否在 parentViewModel.JobMileStones 中(我在第一条评论中写了 parentViewModel.MileStones - 我的错。)。
  • 这给了我:This action is invalid when the mock object ... is in record state. 我不知道为什么它抱怨我处于记录模式,我使用的是 AAA 语法。在尝试返回第二个值之前,是否需要以某种方式重置 Mock?
  • 我现在实际上已经删除了那段代码;经过进一步审查,我意识到它并没有为我的测试添加任何内容。我真正想在这里测试的是,当父级通知其“JobMilestones”集合已更改时,子级通知其“里程碑”集合已更改。不过,我还是很想了解这个问题,所以如果有人能回答,我很乐意给予答案。

标签: .net unit-testing c#-4.0 rhino-mocks


【解决方案1】:

我已经删除了有问题的代码;但是我从来没有弄清楚它为什么会这样。

【讨论】:

    【解决方案2】:

    milestones.Count() 就是这样执行的(因为这是一个 IEnumerable 对象):

    1. 将计数器设置为 0。
    2. 获取第一个元素。
    3. 计数器加 1。
    4. 移动到下一个元素。
    5. 第 3 步直到下一个元素为空
    6. 归还柜台

    所以我建议你重写一下。

    选项1:

    1. 创建不是 IEnumerable 集合,而是创建一些更强大的对象,例如 ListArray

      var milestones = viewModel.Milestones.ToArray();
      //var milestones = viewModel.Milestones.ToList();

      之后,您可以分别使用CountLength 属性进行Assert 检查:

      Assert.That(milestones.Count, Is.EqualTo(1));
      //Assert.That(milestones.Length, Is.EqualTo(1));

    2. 创建一个局部变量来存储计数参数:

      var count = viewModel.Milestones.Count(); // .Count() method executes here. Assert.That(count, Is.EqualTo(1));

    【讨论】:

    • 我明白你在说什么,这有点道理。但我还有一个问题是,对parentViewModel 的调用应该返回一个真正的List&lt;&gt; 对象(注意Expect 调用)。所以对Count() 的调用甚至不需要枚举它,它应该调用列表中的Count 属性。就好像 RhinoMocks 正在重写返回值。
    • @Coding Gorilla 我必须注意您调用的是IEnumerable&lt;Milestone&gt;.Count() 方法,而不是List&lt;Milestone&gt;Count 属性,所以这会导致@987654339 的枚举@.
    • 这不是真的,.Count() 方法足够聪明,可以判断底层类型是否支持 Count 属性,如果该属性可用,将使用该属性。看这里的备注:msdn.microsoft.com/en-us/library/bb535181.aspx
    • @Coding Gorilla 在文章中方法 .Count()Array 对象上被调用。在您的情况下,您调用的是IEnumerable&lt;Milestone&gt;.Count(),因为您将演员阵容从List 转换为Ienumerable。您是否尝试过调用这样的方法:viewModel.Milestones.ToArray().Count()
    • 基础类型是List&lt;&gt;Count() 方法尝试将源转换为ICollection,如果成功则返回Count 属性(我反编译了该方法以验证这)。所以它不应该需要实际枚举集合。然而,调试器显示底层类型是(显然)由 RhinoMocks 生成的代理,我想这是我不理解的部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 2012-07-03
    相关资源
    最近更新 更多