views:

105

answers:

4

I am in the process of writing some test for a server that is implemented in WCF, as the messages are complex and call-backs are made to the clients I wish to include WCF in the tests.

(You may wish to call these “fit” or “integration tests” not unit tests, the code on both side of WCF will have more detail unit test that don’t use WCF.)

As my server keeps state and I wish to check that all channels shut down without errors, I have code like:

    [SetUp]
    public void SetUp()
    {
        //TODO find a fee port rathern then hard coding
        endPointAddress = "net.tcp://localhost:1234";

        mockEngineManagerImp = new Mock<IEngineManagerImp>();              

        EngineManager engineManager = new EngineManager(mockEngineManagerImp.Object);

        serviceHost = new ServiceHost(engineManager);
        serviceHost.AddServiceEndpoint(
            typeof(IEngineManager), 
            new NetTcpBinding(SecurityMode.None),
            endPointAddress);

        serviceHost.Open();      
    }

    [TearDown]
    public void TearDown()
    {
        serviceHost.Close();
    }

However my tests are very slow....

How can I speed up the creation and destroying of my ServiceHost?

+1  A: 

If you're performing several tests in your Fixture, and if there's no side-effect involved, you might want to initialize the host once and for all for the whole fixture, with [FixtureSetup] and [FixtureTeardown], since [SetUp] and [Teardown] are called before and after every test in your fixture.

Other than that, integration testing of WCF services are always a bit of a pain...

Yann Schwartz
I do have side effect, e.g clients register for callback etc. However I *could* add a "Reset()" method to the Server class if forced to do so.
Ian Ringrose
+1  A: 

We stopped writing integration tests which use WCF. It was too much of an effort to make the whole system up and running within reasonable time.

Instead, we're testing the logic isolated. Serialization of data contracts, which is the biggest source for errors in this area, is also tested independent from WCF (just calling the DataContractSerializer). After some initial effort, WCF itself didn't make trouble until now.

I'm not sure if this helps.


Edit: Think of what you are actually testing.

  • What kind of errors do you expect to be found?
  • Is there really no other way to test it? (eg. we found another way for serialization problems)
  • How big is the chance that this kind of error occurs? Is it easy for developers to avoid it?
  • How hard would it be to find it by manual testing? (eg. serialization problems are hard to find, because just one property could be lost, on the other hand, if the client can't even connect, it's very easy to find)
Stefan Steinegger
+1  A: 

We're doing several approaches, depending on what features of WCF are actually in the scope of the test:

If the only required feature really is an ambient transaction (like it would happen with[OperationBehavior(TransactionAutoCompete = true, TransactionScopeRequired = true)]), then we just write a wrapper around the service implementation that sets up and completes a transaction as WCF would do. Then we call that wrapper, and thus the implementation directly, i.e. not via WCF.

If more complicated or advanced features are required, we try to at least switch the transport to named-pipes. Seems like that they are a tat faster, including open/close.

If even the binding/protocol options are important one might argue, that at least now you're really doing integration and not unit testing, YMMV. But anyway in this case we simply use the service as is.

Christian.K
A: 

Thanks for all the great answers – they all contains helpful pointers,

I found that a lot of my tests were not closing the client chancel, this make the close on the server channel wait until the TCP connection from the client had timed out.

Sorting this out led to over a factor of 10 speed up.

Ian Ringrose