2014-08-27 60 views
1

我有一些问题试图使用RhinoMocks来弄清楚,如果在被测试的类中调用方法,也会调用其他一些方法。被测试 我的类:Rhinomocks:我不能正确使用AssertWasCalled

public class OrderMessageHandler : IHandleMessages<UpdateOrder> 
{ 

    public virtual IRepository Repository { get; set; } 

    public void Handle(UpdateOrder message) 
    { 
     if (!message.Order.Confirmed) return; 
     using (var om = new OperationManager()) 
     { 
      try 
      { 
       om.BeginOperation(); 
       LVR.Order.Model.OrderHeader order = ConvertToLocalOrderHeader(message.Order); 
       Repository.SaveUpdate(order); 
       om.CommitOperation(); 
      } 
      catch (Exception ex) 
      { 
       om.RollbackOperation(); 
       // other stuff here 
      } 
     } 
    } 

    internal virtual LVR.Order.Model.OrderHeader ConvertToLocalOrderHeader(Protocol.DTO.OrderHeader order) 
    { 
     // do stuff here, and call Repository.GetAll<Country>() 
    } 
} 

这里是我的测试方法

[Fact] 
public void ConvertToLocalOrderHeader_GivenConfirmedOrderMessage_CallTheConversionMethods() 
{ 
    // create a partial mock 'cause I want some of the implementation to be the true sut class 
    var sut = MockRepository.GeneratePartialMock<OrderMessageHandler>(); 
    // create a stub for the repository, in order to avoid hitting the db 
    sut.Repository = MockRepository.GenerateStub<IRepository>(); 
    sut.Repository.Stub(r => r.GetAll<Country>()) 
     .Return(
      new List<Country> 
       { 
        new Country {CountryID = "IT", Description = "Italy"}, 
        new Country {CountryID = "US", Description = "United States"} 
       }.AsQueryable() 
    ); 
    sut.Repository.Stub(r => r.SaveUpdate<OrderHeader>(Arg<OrderHeader>.Is.Anything)); 

    // call the method I want to test 
    sut.Handle(new UpdateOrder 
     { 
      Order = order, 
      EventId = new Guid(), 
      EventTime = DateTime.Now 
     }); 

    // verify that the method has been called (this is useless in my real test, I put it here just to understand why it doesn't work) 
    sut.AssertWasCalled(s => s.Handle(Arg<UpdateOrder>.Is.Anything)); 
    // verify that an inner method (virtual) has been called during the execution of sut.handle() 
    sut.AssertWasCalled(s => s.ConvertToLocalOrderHeader(order));      
} 

在2个sut.AssertWasCalled电话,我收到一个错误对象引用不设置到对象的实例。 。其原因是,sut.AssertWasCalled作出的方法我正在验证一个电话......这样

sut.AssertWasCalled(s => s.Handle(Arg<UpdateOrder>.Is.Anything)); 

电话

sut.Handle(null) 

而且是空的方法抛出一个异常的参数。 问题太糟糕了,它不应该重新调用这个方法,而只是告诉我它在测试方法之前是否从未被调用过。 这里有什么问题?

编辑:

按在收到的意见建议,我尝试了不同的方法(因为我不喜欢的期望/验证味)。这里的测试方法:

[Fact] 
public void ConvertToLocalOrderHeader_GivenConfirmedOrderMessage_CallTheConversionMethods2() 
{ 
    var mocks = new MockRepository(); 
    var sut = mocks.PartialMock<OrderMessageHandler>(); 
    sut.Repository = mocks.Stub<IRepository>(); 
    sut.Repository.Stub(r => r.GetAll<Country>()) 
      .Return(
       new List<Country> 
        { 
         new Country {CountryID = "IT", Description = "Italy"}, 
         new Country {CountryID = "US", Description = "United States"} 
        }.AsQueryable() 
     ); 
    sut.Repository.Stub(r => r.SaveUpdate<OrderHeader>(Arg<OrderHeader>.Is.Anything)); 
    Expect.Call(() => sut.Handle(Arg<UpdateOrder>.Is.Anything)); 
    sut.Replay(); 
    sut.Handle(new UpdateOrder 
     { 
      Order = order, 
      EventId = new Guid(), 
      EventTime = DateTime.Now 
     }); 
    mocks.VerifyAll();  
} 

ADN这里是我的错误:

System.InvalidOperationException 
Previous method 'OrderMessageHandler.get_Repository();' requires a return value or an exception to throw. 

错误是由代码行,即使这种方法抛出

Expect.Call(() => sut.Handle(Arg<UpdateOrder>.Is.Anything)); 

所以,没有运气...

还有其他想法吗?

+0

您可以尝试使Handle方法为虚拟吗?除非你这样做,否则我认为犀牛不能在这种情况下重写该方法。 – 2014-08-27 14:53:26

+0

mh,你是对的......太糟糕了总体行为没有任何变化:我仍然有同样的问题 – themarcuz 2014-08-27 15:08:00

+0

我想在你的情况下使用Excpect,就像这个例子http://ayende.com/wiki/Rhino+Mocks + Partial + Mocks.ashx?AspxAutoDetectCookieSupport = 1 – 2014-08-27 15:27:41

回答

3

我发现问题所在:方法ConvertToLocalOrderHeader应该声明至少protected internal为了让Rhinomocks重写它。是不够的,作为一个不同类的测试类。 非常简单的解决方案,需要花费数小时才能解决的问题:/