Reputation: 18895
I'm new to using a Mocking framework to mock objects for unit testing. I'm currently using Rhino Mocks and I would think it would have a method to do what I'm not finding it. Here is a LinqPad program (just copy and paste it in a C# program query and it will just work) that shows what I'm trying to do:
public interface MyTest{
int A(int i);
string B(int i);
}
/// This is an actual class that is a black box to me.
public class ActualClass : MyTest {
public int A(int i){
// Does some work
return ++i;
}
public string B(int i){
return A(i).ToString();
}
}
/// I'd like to create a mocked class that uses an instance of the actual class
/// to provide all of the implementations for the interface except for a single method
/// where I can check the parameter values, and provide my own return value,
/// or just call the actual class
public class MockedClass : MyTest {
private ActualClass _actual;
public MockedClass(ActualClass actual){
_actual = actual;
}
public int A(int i){
if(i == 1){
return 10;
}else{
return _actual.A(i);
}
}
public string B(int i){
return _actual.B(i);
}
}
void Main()
{
var mock = new MockedClass(new ActualClass());
mock.A(0).Dump();
mock.A(1).Dump();
mock.A(2).Dump();
mock.B(0).Dump();
mock.B(1).Dump();
mock.B(2).Dump();
}
Results:
1
10
3
1
2
3
What do I do to mock this out for unit testing. Do I need some sort of Dependency Injector?
Upvotes: 2
Views: 709
Reputation: 14697
Yes, you can change the return value of a mocked object based on the parameters passed in. I wouldn't take the approach of mixing a real dependency and a mocked dependency -- too much opportunity for a bug in the real dependency to creep in to your testing.
Here's an example you could use on your MyTest interface that examines the input argument of the mocked method and sets a return value accordingly:
var mock = MockRepository.GenerateStub<MyTest>();
mock.Stub(m => m.A(Arg<int>.Is.Anything))
.Return(99)
.WhenCalled(mi =>
{
var arg = Convert.ToInt32(mi.Arguments[0]);
switch (arg)
{
case 0:
mi.ReturnValue = 10;
break;
case 1:
mi.ReturnValue = 20;
break;
case 2:
mi.ReturnValue = 30;
break;
default:
mi.ReturnValue = -1;
break;
}
});
Note that the "Return(99)" is needed because when you stub a method that returns a value, Rhino.Mocks requires that you either define an exception to be thrown or define a return value. Even though we don't use the return value (since we provide our own inside the WhenCalled handler), it still must be defined or Rhino.Mocks will thrown an exception the first time the stub is called.
Upvotes: 1