2

How to emulate the following behaviour using RhinoMocks?

The tested method invokes ReceivePayment method on an interface.

public void TestedMethod(){
    bool result = interface.ReceivePayment();        
}

Interface has the CashAccepted event. ReceivePayment shoud return true if this event has been invoked several times (or by a condition).

How to accomplish such a task?

update.

Now I do the following:

UpayError error;
        paymentSysProvider.Stub(i => i.ReceivePayment(ticketPrice,
            App.Config.SellingMode.MaxOverpayment, uint.MaxValue, out error))
            .Do( new ReceivePaymentDel(ReceivePayment));

        paymentSysProvider.Stub(x => x.GetPayedSum()).Return(ticketPrice);

        session.StartCashReceiving(ticketPrice);

        paymentSysProvider.Raise(x => x.CashInEvent += null, cashInEventArgs);

public delegate bool ReceivePaymentDel(uint quantityToReceive, uint maxChange, uint maxTimeout, out UpayError error);
public bool ReceivePayment(uint quantityToReceive, uint maxChange, uint maxTimeout, out UpayError error) {
        Thread.Sleep(5000);
        error = null;
        return true;
    }

StartCashReceiving returns immediately since there is a task launch inside. But the next line: paymentSysProvider.Raise(...) is waiting for the completion of the ReceivePayment stub!

Zword
  • 6,605
  • 3
  • 27
  • 52
EngineerSpock
  • 2,575
  • 4
  • 35
  • 57

2 Answers2

2

Are you testing ReceivePayment? If not, you really should not be worried about how that interface is implemented (see http://blinkingcaret.wordpress.com/2012/11/20/interaction-testing-fakes-mocks-and-stubs/).

If you must, you can use the .Do extension method, for example:

interface.Stub(i => i.ReceivePayment()).Do((Func<bool>) (() => if ... return true/false;));

See: http://ayende.com/blog/3397/rhino-mocks-3-5-a-feature-to-be-proud-of-seamless-do http://weblogs.asp.net/psteele/archive/2011/02/02/using-lambdas-for-return-values-in-rhino-mocks.aspx

Rui
  • 4,847
  • 3
  • 29
  • 35
  • Thank you very much. Em... well, I'm trying to test complex behaviour of the class. The ReceivePayment has to return true if the specified condition is satisfied. To satisfy the condition I have to raise the CashAccepted event. – EngineerSpock Dec 23 '13 at 05:28
2

You can use WhenCalled. Actually I didn't understand your question (Is the event fired by the mock or by the unit under test? Who is handling the event?)

There is some sample code:

bool fired = false;

// set a boolean when the event is fired.
eventHandler.Stub(x => x.Invoke(args)).WhenCalled(call => fired = true);

// dynamically return whether the eventhad been fired before.
mock
  .Stub(x => x.ReceivePayment())
  .WhenCalled(call => call.ReturnValue = fired)
  // make rhino validation happy, the value is overwritten by WhenCalled
  .Return(false);

When you trigger the event in your test, you could also reconfigure the mock after firing:

mock
  .Stub(x => x.ReceivePayment())
  .Return(false);

paymentSysProvider.Raise(x => x.CashInEvent += null, cashInEventArgs);

mock
  .Stub(x => x.ReceivePayment())
  .Return(true)
  .Repeat.Any(); // override previous return value.
Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193