I have a class library that interacts with a WCF service, and uses an app.config
file for its configuration. I'd like to unit test this class, but when I run my unit test, I get:
Could not find default endpoint element that references contract 'FooService' in the service model client configuaration section. This might be because no configuration file was found for your application or because no end point element matching this contract could be found in the client element
According to this answer, I need the app.config
file to reside within my unit test project, and indeed this solves the problem. But I really don't want to have to copy my app.config
file around to unit tests every time I change it.
I suppose I could add a link to the app.config
, except that I'm using SlowCheetah to handle app.config
transformations, so my app.config
is generated at compile time.
Is there anything I can do to get this to work, or do I just have to give up on my app.config
and handle the configuration in code?
From the main menu, click DEBUG > Start Without Debugging. This starts the service and invokes the WCF Test Client window.
You can mock the WCF service in your tests. You can inject a version of the the service that doesn't use a WCF service when you are unit testing the class. This way, when the tests run, they don't need to worry about any configuration files. This is also going to lead to a better tests. Presumably you want to test your code, not the WCF service itself. It's better to mock it's behaviour in your tests so you can test only your code.
Create a client wrapper, I did the same thing previously doing a ChannelLocator<T> that implemented IChannelLocator<T> and underneath it mostly wrapped a channel factory's behavior.
However be very careful that this abstraction is not leaking connections underneath, the ChannelFactory's channel management mechanisms are complex and should be studied carefully to avoid leaking client or server channels which may make either of them unresponsive.
Remember this pattern:
try
{
yourChannel.Close();
}
catch
{
yourChannel.Abort();
}
Then in your unit test, you merely Mock<IChannelLocator<T>> and you can create a great deal more scenarios in your code for instance you can test how your code responds when the client makes a request and get's a timeout exception, etc. Furthermore this will make your tests run exceedingly fast and on anyone's machine with no configuration because your test no longer depends on an actively running service.
What happens if that actively running service has a bug causing the unit test to fail, or worse pass inaccurately? It's a little more work to wrap your dependencies in abstraction layers for testing, but completely worth the trouble.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With