Embedding an ASP .NET application in a unit test (part 2)

In the previous part of this series I talked about how we set up a unit test to run a web application under an embedded instance of the Cassini web server. This takes care of the central component of the diagram below that illustrates our architecture.

So what about mocking the entire backend?

Step 2: mocking an object and redirecting it back to the test assembly

Apart from that, we can only influence the application by using it’s HTTP interface or by modifying web.config. Obviously we don’t want to achieve test compatibility by extending the public access surface.

Before I talk about our solution, let’s sum up the requirements:

we want to inject a mock of a SOAP API into an isolated web application,

building the mock should be as simple as possible, since we may want build a different one in each unit test,

we need complete access to the mock object to verify if and how it was called,

the object should be statefull, otherwise we will need to manage sessions ourselves,

the final solution should work on Mono.

The only possible solution meeting these requirements that we could think of was .NET Remoting. What we did was expose an API implementation with .NET Remoting, and modify web.config before test execution to point to the location of this object. The fact that the gateway never uses the WebService class directly, only a wrapper exposed through IoC, greatly helped.

Changes to application under test

Almost everything user-accessible in SymbolSource is coded against the following interface (of course it’s a bit bigger in reality), which wraps the server SOAP API:

As you can see, if no redirect was requested in web.config, IManagementProxy will be implemented by a really boring class that just creates the WebService class generated by Visual Studio’s Add service reference dialog. If there is, however, a factory method is registered that looks like this:

Nothing really fancy, just using the URI passed in from web.config to activate a remote object, which in this case is factory returning objects implementing IManagementProxy. We need a factory here, because there is no way to control .NET Remoting object instantiation on the server (unit test). It’s always constructed by the .NET Framework, either in singleton or per-request mode, and we want to provide our own pre-configured instance. IManagementProxy and IManagementProxyFactory are classes that of course need to come from a library shared between the web application and test project.

.NET Remoting setup in a unit test

Let’s switch now to an actual test case. Here’s an example that tries to push a package:

That’s a bit chunk of code, I admit, but we wanted it to be failry robust and flexible, so it does endpoint reference counting, and maintains a stack of mock proxy objects to allow scoped switching. The most important part is calling RemotingConfiguration.RegisterWellKnownServiceType to register the factory, ChannelServices.RegisterChannel to open a TCP listener and IManagementProxyFactory.Create, which returns the most recently registered mock.

Here’s the part of web.config defining the redirect URI. A very good idea would be to apply it as a transformation on a copy of the web application before testing it. Or you can just keep the test-friendly version in your source code repository and remove the redirect as part of a normal deployment.