Background
When unit testing our code, we shouldn't depend on external resources such as web services. To do this, we should stub those web services in our unit test. The easiest way to stub a class method is by using a mocking framework such as Moq.
The Problem
When using Visual Studio's Add Service Reference tool to create a proxy class to call the web service, this generated code looks something like this:
public partial class MyWebServiceSoapClient :
System.ServiceModel.ClientBase<MyWebServiceSoap>, MyWebServiceSoap {
MyMethodResponse MyWebServiceSoap.MyMethod(MyMethodRequest request) {
return base.Channel.MyMethod(request);
}
public string MyMethod(string parm) {
}
}
The Moq framework can only mock methods that are in part of an interface or are virtual.
As you can see, MyWebServiceSoap
is an interface, but the method signature it contains is not the one we publicly call, but the method with the request/respond signature. Also notice that the public MyMethod
is not virtual.
So how can we mock it using Moq?
Solution 1
Change the generated code to include the virtual
keyword on the public
method.
Pros: It is the easiest way.
Cons: Changing generated code is generally not a good advice, as you or your co-worker can regenerate the code and then you will need to go and change it again.
Solution 2
Create a proxy class to warp the generated code.
Pros: Very easy to understand your code.
Cons: I don't like the idea to introduce a proxy around a proxy just for the test.
Solution 3
Mock the interface (MyWebServiceSoap
in the above example).
Pros: There is no need to change the production code to unit test it.
Cons: It is a lot of work to generate to request/response objects and also the unit test is not understandable as the stubbed method is not the one actually called.
Solution 4
Use the fact that the generated class is marked with the partial
keyword to add an interface to the class.
For example, in a different file, add the following code:
public interface IMyWebServiceSoapClient {
string MyMethod(string parm);
}
public partial class MyWebServiceSoapClient: IMyWebServiceSoapClient {}
Now, we can use the interface IMyWebServiceSoapClient
in our business logic code and we can easily test it by mocking the interface.
Pros: Makes the unit test simple to read and maintain.
Cons: Need to add code to my production code.
Conclusion
There are a lot of ways to mock the web-services. While Solution 2 is the most widespread, I like solution 4 as it makes my unit test simpler to read and maintain.