Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rhino Mocks overwriting stubs possible?

I have this problem, which may be a bug in Rhino Mocks 3.5:

stubObj = MockRepository.GenerateStub(IObject);

stubObj.Stub(a=>a.Get()).Return (Guid.Empty); //1.stub
stubObj.Stub(a=>a.Get()).Return (Guid.NewGuid()); //2.stub, should overwrite the first one?

this:

var value = stubObj.Get(); 

returns Guid.Empty, is this the correct behavior?

like image 999
David Avatar asked Feb 19 '10 08:02

David


People also ask

What is a stub vs mock?

Stub: a dummy piece of code that lets the test run, but you don't care what happens to it. Substitutes for real working code. Mock: a dummy piece of code that you verify is called correctly as part of the test. Substitutes for real working code.

Which is a valid mock type using Rhino?

Rhino. Mocks supports three basic types of mock objects: Strict Mock. A strict mock requires you to provide alternate implementations for each method/property that is used on the mock.


3 Answers

If you want to return the empty guid a known number of times, the only thing you have to do is to tell RhinoMocks how many times to repeat it, e.g. the following test passes:

[Test]
    public void MultipleStubsTest()
    {
        var testMock = MockRepository.GenerateMock<ITest>();
        testMock.Stub(x => x.Get()).Return(Guid.Empty).Repeat.Once();
        testMock.Stub(x => x.Get()).Return(Guid.NewGuid());

        Assert.AreEqual(Guid.Empty, testMock.Get());
        Assert.AreNotEqual(Guid.Empty, testMock.Get());
    }

if you don't know how many times Get() will be called before the guid should change, than you can always use .Do() and code it there (please let me know if you need more details).

like image 182
Grzenio Avatar answered Sep 16 '22 21:09

Grzenio


You have just programmed the Stub object for two separate calls. If you call stubObj.Get again, you should get what Guid.NewGuid generated. You can prepare your fake object for any number of invocations of different kinds. For this reason, it doesnt make sense to expect the last .Stub call for a given invocation to replace previous .Stubbings of that call.

In your test code, which should be short and neat, there should never be a case where you need to 'undo' such programming of the mock in the way you seem to want to do.

If what needs to be returned is a conditional thing which varies depending on other bits of your test code across multiple calls to this block of code, the last thing you want is magic happening to make readers have to figure out what you meant. If it's conditional, you should make it clear.

And then, when you've made it clear, refactor it out as you should not have Conditional Logic in Tests (see xUnit Test Patterns)

like image 35
Ruben Bartelink Avatar answered Sep 17 '22 21:09

Ruben Bartelink


That's how you would do it. It passes on my machine.

    [TestMethod]
    public void Test()
    {
        stubObj = MockRepository.GenerateMock<IGuidTest>();

        stubObj.Stub(a => a.Get()).Repeat.Times(1).Return(Guid.Empty);
        stubObj.Stub(a => a.Get()).Repeat.Times(1).Return(Guid.NewGuid()); 

        Assert.AreEqual(Guid.Empty, stubObj.Get());
        Assert.AreNotEqual(Guid.Empty, stubObj.Get());

    }
    public IGuidTest stubObj;
    public interface IGuidTest
    {
        Guid Get();
    }
like image 38
Usman Avatar answered Sep 18 '22 21:09

Usman