views:

44

answers:

3

I'm currently building a .net web application that uses WCF web services to allow a Flex front end to access the database.

I'm in the process of setting up some unit/integration style testing on the web services and am trying to work out the best way to allow the tests to access and modify data in a separate test database.

Currently, the connection string in my unit test project points to my testing database, and the connection string in my web services project points to my development database. However, as I am using Linq it appears that when I call the web service methods from my test class, it uses the development database connection string.

I have looked into creating mock objects or in-memory database but I believe the same issue would occur.

Is there a way to get this to work, or is my entire idea about what I want incorrect, in which case is there a better way to set this up? I'm still early enough in my project that I'm not adverse to significantly changing the architecture of the solution.

A: 

Make sure the code in the web service is minimal and not much more than a simple call to your service layer. When you do that you can skip calling the web service directly, and create an integration test suite that also calls your service layer. In that case you are doing an in-process call instead of an call over the network. In that situation it will be much easier to ensure the right database is accessed and you can easily wrap those calls with database transactions that will be rolled back. You certainly want to rollback any actions to the database, because it will be very hard to maintain RTM tests. One way to do this is by using TransactionScope inside tests.

Good luck.

Steven
+1  A: 

Steven's suggestion is to do away with the WCF plumbing for the tests. This would certainly work and test much of the business logic, but I would want my automated integration tests to test the WCF interactions as well.

I've successfully achieved this in automated tests for my project.

Note that it is possible for the WCF client and WCF host to share the same process. In this case, it is still making the calls through the WCF framework, with all of the constraints and complications. And your WCF services will pick up the connection string from you test project's configuration file.

Just to illustrate this, here is what the configuration file could look like if the client and service are in the same process.

<configuration>
  <connectionStrings>
    <add name="ContractsManager" 
         providerName="System.Data.SqlClient" 
         connectionString="Data Source=localhost;Initial Catalog=ContractsManager_AutoTest;Integrated Security=True;Pooling=False;Asynchronous Processing=true;Application Name=CmAutoTests"
         />
  </connectionStrings>
    <system.serviceModel>

        <client>
            <endpoint
                name="LoggingService"
                address="net.tcp://localhost:9612/loggingService"
                binding="netTcpBinding"
                contract="ContractsManager.ILoginService" />
        </client>
        <services>
            <service name="ContractsManager.LoginServiceImpl">
                <endpoint
                    address="net.tcp://localhost:9612/loggingService"
                    binding="netTcpBinding"
                    contract="ContractsManager.ILoginService">
                </endpoint>
            </service>
        </services>
    </system.serviceModel>
</configuration>

This way your automated tests will find bugs that are specific to WCF (for example, throwing an exception that isn't specified by a Fault Contract). I was saved by this today: my code had a bug which meant that channels weren't being closed properly. My tests kept hanging because the throttling limit was being reached. It took some time to figure out, but I'm thankful the bug didn't find it's way into production.

Your test suite should set up the service hosts before the first test is run. (I've tried setting up and tearing down the service hosts with each test, but it runs too slowly).

Good luck.

Andrew Shepherd
A: 

Since a WCF web service class is not bound to the ASP.Net infrastructure (don't have to inherit from Syste.Web.Services.WebService), you can easily inject a reference to a repository or an object context into the service. Then you can test whatever logic is in the web service itself using unit tests that will use some mock in-memory repository and therfore run very quickly. On the other hand, the integration tests will use some real database and you can catch the errors related to the persistence layer there. So I'd disagree with Steven that the web service methods should be just one-line ones that call some service layer, unless the logic is so heavy that deserves its own class(es).

Ivan Gerken