Initially it seemed like a dud but when I left it for a while and came back to it later I discovered that the solution is simple but not so obvious. I am not going to cover the basics of Moles, you can google that for yourself, I'm going to cover the necessary steps to get your WCF proxies (or whatever similar case) stubbed for unit testing purposes.
The problem that I had with Moles and WCF was that the proxy classes inherited from ClientBase (which wasn't the problem) which in turn inherited from IDisposable. Now since a proxy's constructor tries to check the configuration file for proxy configuration, I had to sub the constructor of that proxy with an empty delegate. I managed to stub the proxy call with something that returned a dummy value and running through the tests, it actually stubbed that proxy call which is what I wanted.
This was fine but I had a couple of proxies wrapped around a 'using' statement and at the end of a using statement the proxy's Dispose() method gets called and I got greeted with a nice NullReferenceException. I realised it was because I stubbed the constructor but when I checked for the Dispose method to stub, I couldn't find it anywhere in the generated Moled-Proxy class. That's the part that messed me around.
After some thinking and some Googling I started to think that I might have to "mole" the System.ServiceModel assembly in order to stub the Disposable method found in the ClientBase<> class. This also had a minor problem. It caused a compiler error but after some Googling someone recommended that I amend the 'System.ServiceModel.moles' file with the following:
Beneath the <Assembly> tag just add the following:
<StubGeneration>
<Types>
<Clear/>
<Add Namespace="System.ServiceModel.Description!"/>
</Types>
</StubGeneration>
When you compile the unit test project it should finally generate the moled System.ServiceModel assembly and now we can finally stub that method! Now suppose you had a proxy which had the contract of IGeneral, you would stub its Disposable method like so:
MClientBase<IGeneral>.AllInstances.SystemIDisposableDispose = (c) => { };
Unfortunately you cannot just specify the MClientBase<> without specifying a Type. It will give a compiler error.
So by using an example unit test:
[TestMethod]
[HostType("Moles")]
public void TestMethod1()
{
MGeneralProxy.AllInstances.GetName = (p) => "Stubbed Name";
MGeneralProxy.Constructor = (p) => { };
MClientBase<IGeneral>.AllInstances.SystemIDisposableDispose = (c) => { };
using (GeneralProxy p = new GeneralProxy())
{
Assert.AreEqual("Stubbed Name", p.GetName());
}
}
You should be able to successfully run it and stubbing the proxy call for your unit test to work.
the 'using' block should actually be the part where the production code gets executed but for demonstration purposes, I left it as is so that you can get the idea that the proxy gets stubbed as it should.
Here is the rest of the code for some clarity:
public interface IGeneral
{
string GetName();
}
public class GeneralService : IGeneral
{
public string GetName()
{
return "General Name";
}
}
public class GeneralProxy : ClientBase<IGeneral>, IGeneral
{
public string GetName()
{
return Channel.GetName();
}
}
1 comment:
Thats really awesome. I am searched for a solution for that an entire day.
Post a Comment