views:

90

answers:

5

Hello all,

(C#, WCF Service, Rhino Mocks, MbUNit)

I have been writing tests for code already in place (yes I know its the wrong way around but that's how its worked out on my current contract). I've done quite a bit of re-factoring to support mocking - injecting dependencies, adding additional interfaces etc - all of which have improved the design. Generally my testing experience has been going well (exposing fragility and improving decoupling). For any object I have been creating the dependant mocks and this sits well with me and makes sense.

The app essentially has 4 physical layers. The database, a repository layer for data access, a WCF service that is connected to the repository via a management (or business logic) layer, so top down it looks like this;

WCF Managers Repository Database

Testing the managers and repository layer has been simple enough, mocking the dependencies with Rhino Mocks and injecting them into the layer under test as such.

My problem is in testing the top WCF layer. As my service doesn't have the constructor to allow me inject the dependencies, I'm not sure how I go about mocking a dependency when testing the public methods (ServiceContracts) on the service.

I hope that's made sense and any help greatly appreciated. I am aware of TypeMockIsolator etc, but really don't want to go down that route both for budget and other reasons I won't go into here. Besides I'm sure there are plenty of clever 'Stackers' who have the info I need.

Thanks in advance.

A: 

You could make the WCF services a thin layer over the 'managers', so they have little or no logic in them which needs testing. Then don't test them and just test the managers. Alternatively, you could achieve a similar effect by having another 'service' layer which contains the logic from the services, which can be tested, and make the actual WCF code just pass through to that.

Grant Crofton
Ok .. thanks for that .. I had considered doing something similar but was trying to avoid introducing a layer. But nice to have it confirmed as a possibility.
Simon Rigby
A: 

Our WCF service gets all its dependencies from a Factory object, and we give the service a constructor which takes IFactory. So if we want to write a test which mocks one of the dependencies, say an IDependency, we only need to inject a mock factory, which is programmed to give mocked IDependency object back to the service.

Jonny Cundall
Am I right in saying that you are effectively introducing a second constructor just to allow you to configure it for testing? Not saying I disagree, just making sure I understand it.
Simon Rigby
Yep, I'm not saying it's great, it's just what we use and it works OK.
Jonny Cundall
I've used this approach as well to enable testing of legacy code that was not designed for it. It's a bit ugly, but it's effective.
Dan Bryant
A: 

If your using an inversion of control (IoC), such as Unity, AutoFac or Castle Windsor, and a mocking framework (eg. Moq, NMock, RhinoMocks) this is simple enough as long as you have the right design.

For a good tutorial on how to do it with RhinoMock and Windsor, take a look at this blog article - http://ayende.com/Blog/archive/2007/02/10/WCF-Mocking-and-IoC-Oh-MY.aspx

Mike737
Hi .. and thanks for the article (good read) but I think its not quite what I'm looking for. The article refers to mocking the service. I don't really want to mock it, I want to test it, but it has dependencies that I need to mock that I can't inject. (unless I've missed something)
Simon Rigby
+1  A: 

Is there a specific reason you cant have a constructor on your service?

If not, you can have overloaded constructors with a default constructor wiring up the defaults and one parametrized constructor with your dependencies. You can now test the parametrized ctor and rely on the default ctor for creating the instance in production.

public MyService() : this(new DefaultDep1(), new DefaultDep2())
{
}

public MyService(IDep1 d1, IDep2 d2)
{
}

A better solution if you use dependency injection would be to use the WCF IInstanceProvider interface to create your service instance and provide the needed dependencies via that injection point. An example using Structure Map can be found here.

PHeiberg
Thanks that does sound like the route I need to go down. Thanks for the link .. very useful.
Simon Rigby
Thanks all for your help. Whilst some of the answers were similar .. picked this one as it was succinct and indicates a direct solution to the problem. Thanks all again.
Simon Rigby
A: 

If you're using Castle Windsor, take a look at the WCF facility, it lets you use non-default constructor and inject dependencies into your services, among other things.

Mauricio Scheffer
I'm not no .. but I'm getting the feeling I should be looking at it :). Thanks for the tip.
Simon Rigby