I'm trying out Rhino mock on a new project at the moment, trying to get into the TDD groove (which, thanks to NUnit, I am). I've started my codebase with interfaces and a couple of implementations, writing my tests before the classes like a good boy. All was going well, Rhino mock proving to be adaptable and reasonably concise in its operations when I hit upon a scenario that had me stumped.
I have an ProcessOutboundRouter class that implements the interface IProcessOutbound, this router wraps up calls to a list of other IProcessOutbound instances, forwarding messages to the correct instance on the basis of policies (defined by the IServicePolicy interface). The router does this by matching the value of a ServiceType property on the policy to the type of the IProcessOutbound instance. When it came to testing I'd originally setup my test thus:
1: [Test]
2: public void SendMessage_TwoOutbound_RoutedToTwoCorrectly()
3: {
4: IProcessOutbound outbound1 = _mockRepository.StrictMock<IProcessOutbound>();
5: IProcessOutbound outbound2 = _mockRepository.StrictMock<IProcessOutbound>();
6: ProcessOutboundRouter router = new ProcessOutboundRouter();
7: router.Add(outbound1);
8: router.Add(outbound2);
9:
10: IServicePolicy policy1 = _mockRepository.StrictMock<IServicePolicy>();
11: IServicePolicy policy2 = _mockRepository.StrictMock<IServicePolicy>();
12:
13: Dictionary<string, string> data = new Dictionary<string, string>();
14:
15: Expect.Call(policy1.ServiceType).Return(outbound1.GetType());
16: Expect.Call(delegate { outbound1.SendMessage(data, new IServicePolicy[] { policy1 }); });
17: Expect.Call(policy2.ServiceType).Return(outbound2.GetType());
18: Expect.Call(delegate { outbound2.SendMessage(data, new IServicePolicy[] { policy2 }); });
19:
20: _mockRepository.ReplayAll();
21: router.SendMessage(data, new IServicePolicy[] { policy1, policy2 });
22: _mockRepository.VerifyAll();
23: }
Alas, 'twas not to be... I'd hoped that the StrictMock<T> method would return different mocks with different types when creating multiple mocks of the same interface. Understandably it doesn't, both outbound1 and outbound2 are of the same proxy type generated by Rhino mock. Creating a new MockRepository instance doesn't help either. So I've, somewhat unfortunately, ended up with the following:
1: [Test]
2: public void SendMessage_TwoOutbound_RoutedToTwoCorrectly()
3: {
4: IProcessOutbound outbound1 = _mockRepository.StrictMock<IProcessOutbound>();
5: IProcessOutbound outbound2 = _mockRepository.StrictMock<IMockProcessOutbound>();
6: ProcessOutboundRouter router = new ProcessOutboundRouter();
7: router.Add(outbound1);
8: router.Add(outbound2);
9:
10: IServicePolicy policy1 = _mockRepository.StrictMock<IServicePolicy>();
11: IServicePolicy policy2 = _mockRepository.StrictMock<IServicePolicy>();
12:
13: Dictionary<string, string> data = new Dictionary<string, string>();
14:
15: Expect.Call(policy1.ServiceType).Return(outbound1.GetType());
16: Expect.Call(delegate { outbound1.SendMessage(data, new IServicePolicy[] { policy1 }); });
17: Expect.Call(policy2.ServiceType).Return(outbound2.GetType());
18: Expect.Call(delegate { outbound2.SendMessage(data, new IServicePolicy[] { policy2 }); });
19:
20: _mockRepository.ReplayAll();
21: router.SendMessage(data, new IServicePolicy[] { policy1, policy2 });
22: _mockRepository.VerifyAll();
23: }
Notice the second IProcessOutbound instance is a mock for a different interface (IMockProcessOutbound, which merely inherits IProcessOutbound without adding anything). Whilst this works, it's nowhere near a final solution, what happens if I need a third instance (again of a different type)? Another interface? Not a good pattern.
Has anyone managed to achieve the desired effect without having to resort to the new interface trick?