views:

284

answers:

2

I certainly hope someone can help ease my frustration. I am trying to find a good way to unit test my WCF service implementation classes but every resource that I've found providing a solution is limited to services with only a single method/operation.

In my case, I have a service class which contains several service methods/operations. The purpose of the service class is to provide the interface to behavior that is implemented within the core application. As such, each method/operation is responsible for:

  1. accepting a Request object from the caller
  2. validating the object's properties
  3. creating an instance of the applicable Command object that carries out the operation
  4. mapping the Request object's properties to the Command object.
  5. executing the Command object
  6. mapping the results to a Response object
  7. returning the Response to the caller

In addition, the service method handles any exceptions that occur and return a WCF Fault.

We are using Spring.NET for both IoC (DI) and AOP. The service class is instantiated by Spring which allows us to use Spring's ParameterValidation aspect to perform step 2. By default, we use Spring for step 3 as well.

For the most part, all of this is working great. However, when it comes time to write unit tests to verify the behavior of a service method I get bogged down trying to figure out the right way to deal with the service's dependencies on multiple Command objects (one per method).

Let's be clear, I don't have a problem mocking the Command objects (we use Moq, btw) nor do I have an issue doing black box testing. I am trying to do white box testing on the internal logic, such as verifying that step 4 is performed correctly or if the Command object throws an exception, the service handles it correctly. For these I am using mock instances of the Command object.

The problem is finding the best practice for a scenario where the object under test has multiple dependencies - especially when I am only interested in one of them for the test I am running.

The Constructor approach to DI just isn't practical as I would need to have as many arguments to the constructor as I do methods on my service (and that could be quite a lot). Setter-injection concerns me because the setters would only exist for the purpose of testing - and, again, there would be a large number of them in many cases.

The service is designed to delegate step 4 to a virtual method that, by default, uses Spring to instantiate the Command object but van be overridden to return the mock using the inherit-and-override approach. But this has proven to be unwieldy as well.

So, after pouring over article after article online that demonstrate various solutions but, as I said, only ever reflect a service with one method/operation, I am looking for some guidance for an approach that will be easy to implement, maintain and extend when dealing with real-world services that contain multiple methods and multiple dependencies.

Keep in mind that I can't use Spring to inject mocked Command objects because I need references to the mocks in order to set them up and verify the method's behavior. (Not to mention that my tests are then dependent upon Spring working correctly, too.)

+1  A: 

I usually have my service classes be nothing but thin facades to the real functionality. In that case, you might consider forgoing testing the service itself, but have it delegate all calls to one of multiple inner objects, which would be individually more testable as they would be more specific.

kyoryu
That's essentially what we are doing but I still want to test that the delegation is working properly. For instance, if I change a property on my internal object (the one I am delegating to), then maybe that object still works correctly but I will no longer be mapping the Request object correctly in my service method.
SonOfPirate
A: 

Sounds like you have already done most of the hard works.

Since you are already using a DI container perhaps you could simply create and inject Mocks that intercept step 3. You could then what is received by the DI container and how the validation behaves to test the first two steps then you could have the Mock return whatever you want to test the remaining steps.

You have already taken a large dependence on spring.net and going that extra distance to inject your mocks and force tests to use them sounds reasonable to me. There must be a way of modifying your config temporarily to use a specific Mock. If not consider a simple factory to be used by your service to allow you to get your Mocks in place.

smaclell
I realize I have just re iterated your last paragraph but if spring.net is getting in the way of testing then work around it.
smaclell