代码之家  ›  专栏  ›  技术社区  ›  RodH257

为什么犀牛嘲笑一个树桩上的错误,而不是模仿一个完全相同的事情?

  •  2
  • RodH257  · 技术社区  · 14 年前

    我对Rhino Mocks还比较陌生,刚开始用这个项目。

    我正在测试一些代码,这些代码调用一个外部方法来获取“project”的IEnumerable,我为它提供了一个接口,这样我就可以截取/模拟它了。

    在我的单元测试开始时,我测试了一些迭代于IEnumerable的代码(或调用count(),两者都会导致错误),我设置了一个存根实现。

    IJobProcess stub = MockRepository.Stub<IJobProcess>();
    SetupResult.For(stub.CheckTeamMeetingInLastMonth(null)).IgnoreArguments().Return(true);
    SetupResult.For(stub.GetOutstandingActions(null)).IgnoreArguments().Return(
                        new List<ProjectActionsDomain.DomainObjects.ProjectAction>()
                        );      
    

    但是,这会导致:

    PmqccFormTests.GetFlagsReturnsIncompleteFlagWhenIncomplete : FailedSystem.InvalidOperationException : Previous method 'IEnumerator.MoveNext();' requires a return value or an exception to throw.
    at Rhino.Mocks.Impl.RecordMockState.AssertPreviousMethodIsClose()
    at Rhino.Mocks.Impl.RecordMockState.MethodCall(IInvocation invocation, MethodInfo method, Object[] args)
    at Rhino.Mocks.MockRepository.MethodCall(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
    at Rhino.Mocks.Impl.RhinoInterceptor.Intercept(IInvocation invocation)
    at Castle.DynamicProxy.AbstractInvocation.Proceed()
    at System.Linq.Enumerable.Count(IEnumerable`1 source)
    at PmqccDomain.DomainObjects.PmqccForm.GetFlags() in PmqccForm.cs: line 387
    at PmqccUnitTests.PmqccFormTests.GetFlagsReturnsIncompleteFlagWhenIncomplete() in PmqccFormTests.cs: line 426 
    

    但是,如果我把这个改成

            IJobProcess mock = MockRepository.GenerateMock<IJobProcess>();
    
            mock.Expect(x => x.GetOutstandingActions(null)).IgnoreArguments().Return(
                new List<ProjectActionsDomain.DomainObjects.ProjectAction>());
            mock.Expect(x => x.CheckTeamMeetingInLastMonth(null)).IgnoreArguments().Return(true);
    

    它没有错误,我认为存根是一个没有在其结果上断言的模拟?还是我错了?在使用模拟时,Rhino模拟有哪些不同之处可以避免错误?

    3 回复  |  直到 14 年前
        1
  •  5
  •   aqwert    14 年前

    正如jonny c强调的那样,我认为setupresult与mockrepository.generatertestub不兼容。

    SETUPRESULT将与使用lamba表达式之前Rhino使用的预期记录和播放功能一起使用。

    首选的方法是使用稍后介绍的arrange-act-assert语法,但是在查看Rhino API时,很难知道要为AAA使用什么。

    我要做的是只保留需要返回值并断言在末尾调用了方法的存根方法/属性。

    所以应该做的是…

    //Arrange
    IJobProcess stub = MockRepository.GenerateStub<IJobProcess>();
    stub.Stub(x => x.CheckTeamMeetingInLastMonth(null)).IgnoreArguments().Return(true);
    stub.Stub(x => x.GetOutstandingActions(null)).IgnoreArguments().Return(
                    new List<ProjectActionsDomain.DomainObjects.ProjectAction>()
                    );   
    //Act
    -- Perform SUT --
    
    //Assert
    stub.AssertWasCalled(x => x.CheckTeamMeetingInLastMonth(someExpectedValue));
    

    useage of SetupResult

    usage of AAA

        2
  •  3
  •   Jonny Cundall    14 年前

    我不确定SetupResult.for是如何使用的,但要终止通常使用的方法

    stub.Stub(j => j.CheckTeamMeetingInLastMonth(null))
    .IgnoreArguments().Return(true);
    

    做你想做的事情。mock.stub()也可以用于相同的目的。

        3
  •  0
  •   Grant Crofton    14 年前

    需要注意的一点是

    IJobProcess mock = MockRepository.GenerateMock<IJobProcess>();
    

    IJobProcess stub = MockRepository.GenerateStub<IJobProcess>();
    

    因此,为了直接进行比较,您可能希望尝试这种方式进行存根,并查看是否使用相同的语法得到错误。

    但要回答你的问题,是的,存根就是这样,我不知道为什么会失败(尽管我不熟悉你使用的存根语法)。有一个关于 mailing list here 可能与此有关。