views:

82

answers:

4

hey guys

I'm new to mocking, and I'm having a hard time solving an issue with UnitTesting.

Say I have this code:

public class myClass{

    private IDoStuff _doer;

    public myClass(IDoStuff doer){
        _doer = doer;
    }

    public void Go(SomeClass object){

        //do some crazy stuff to the object

        _doer.DoStuff(object) //this method is  void too
    }
}

Ok, so I want to UNIT test the Go method. I don't care what the _doer object does to the object once is gets it.

HOWEVER, I do want to inspect what the _doer object has received.

in PSEUDO code I want to achieve this:

[Test]
public void MyTest()
{
    IDoStuff doer = Mocker.Mock<IDoStuff>();
    Guid id = Guid.NewGuid();

    //test Go method
    new MyClass(doer).Go(new SomeClass(){id = id});

    Assert.AreEqual(id,MockingFramework.Method(DoStuff).GetReceived<SomeClass>().id);
}

Is this possible using Rhino, and if so, how do I achieve it?

cheers

+3  A: 

I think what you have is good so it'd be:

IDoStuff doer = MockRepository.GenerateMock<IDoStuff>();

then set up the expectation via:

doer.Expect(() => DoStuff(id));

then at the end:

doer.VerifyAllExpectations();

EDITED from Lee's answers to note that you can also do stuff like:

doer.Expect(d => d.DoStuff(Arg<int>.Is.GreaterThan(5))

or

doer.Expect(d => d.DoStuff(Arg<CustomObject>.Matches(x => x.CustomProperty == "Beef")));

or similar tests when you don't want exact reference comparisons by using the Arg and Arg objects.

Wysawyg
+1 sweet, cheers dude, I'll try it out now
andy
+1  A: 

If you just want to test that the MyClass instance passes its parameter to doer.Go then you can just set up an expectation:

SomeClass obj = new SomeClass { id = id };

doer.Expect(d => d.DoStuff(obj));

//test go method
new MyClass(doer).Go(obj);

doer.VerifyAllExpectations();

However if you want to check that it passes some possibly different object with some particular value for a property, then you can use a constraint:

doer.Expect(d => d.DoStuff(null))
    .IgnoreArguments()
    .Constraints(Property.Value("Id", expectedId));
Lee
+ 1: hmm... interesting. cool, I'll check this out too
andy
+2  A: 

With the new Arrange/Act/Assert syntax:

[Test]
public void MyTest()
{
    // arrange
    IDoStuff doer = MockRepository.GenerateStub<IDoStuff>();
    MyClass myClass = new Myclass(doer);
    Guid id = Guid.NewGuid();

    // act
    myClass.Go(new SomeClass(){id = id});

    // assert
    doer.AssertWasCalled(x => x.DoStuff(
        Arg<Someclass>.Matches(y => y.id == id)));
}
Wim Coenen
hi wim, what do you mean by "new" Arrange/Act/Assert, and what's the diff between stub and StrickMock? cheers
andy
cool, this is exactly what worked, cheers!
andy
@andy: I have blogged about the difference here: http://mindinthewater.blogspot.com/2010/02/mocking-frameworks-stubs-vs-mocks.html
Wim Coenen
hey Wim, just checked out your blog, I'm a capoerista too... I think it compliments programming quite nicely ;-)
andy
+1  A: 

All of these answers provide various ways to do what you want and all of them work. There's one additional thing to be aware of. If you need to get really "low level" and check out arguments passed to any stubbed/mocked method, you can use GetArgumentsForCallsMadeOn.

It's a little messy as it returns object[][]. You use it like this (assuming you stubbed stubber.InsertData to accept null):

var args = stubber.GetArgumentsForCallsMadeOn(s => s.InsertData(null));

args[0] is an array of parameters passed to InsertData the first time it was called.

args[1] is an array of parameters passed to InsertData the second time it was called.

etc...

So if you wanted to see the integer value passed as the second parameter of the first invocation of some method you could:

var check = (int) args[0][1];

Again, I'd recommend one of the previous methods, but this is available if you need to get really down and dirty to check out arguments.

Patrick Steele
cool, cheers patrick. this is my first time mocking, it's really powerful, cheers!
andy