I've implemented a subscribe/publish (for my own enjoyment) WCF service which works reasonably well. Like all blogs and books I've seen they all use OperationContext to get the clients callback address. After a bit of reading, due to many people saying not to use OperationContext, I found myself not being able to create proper unit tests. Yet I haven't been able to find an alternative. I suppose the subscribe method could accept a parameter for it to provide its own address? I could see the code being testable from an intergration test stand point of view but not for unit testing since OperationContext would always be null.
How do I get the clients endpoint when they subscribe to my service without using OperationContext?
Little bit of an aside but where is a good WCF resource with testing in mind when showing code samples? There are tons of blogs out there reiterating the same code without providing sample test cases.
Thank you.
Microsoft developers really like sealed and static keywords (as well as internal) and they hate virtual. Because of that standard testing approaches and framworks often don't work. You have two choices:
Wrap access to OperationContext in custom class and inject an instance of the class to your service. This will involve additional work because you will need to do injection somewhere outside your service. For example constructor injection will need custom IInstanceProvider.
Use more poweful testing framework. Check Moles framework which is able to intercept calls and redirect them. This enables "mocking" sealed classes and static methods/properties.
Another approach is simply refactoring your code. Take away all business logic from your service into separate testable business class and let the service participate only in integration test. Service is more like infrastructure and not everything really needs unit test. Integration / end-to-end / behavior test is also test and valid approach.
Related
I’ve seen lots of info on this topic but wanted to provide a specific example and ask some specific questions.
I’m currently in the middle of a development project in which I’m programming against a telephony system via the OEM provided SDK. I’ve created several interfaces & classes that extend the functionality of the SDK and have refactored these to support dependency injection for ease of testing. At the lowest level, I have methods like “retrieveUserInfo” that accepts a connection interface and a query object.
When Unit testing, I could actually create a connection to the telephony system, get back a given user, and check it for the correct data. This test is meaningful to me as it lets me know both my Middleware and the underlying OEM libraries are working correctly; however, because it’s actually creating a connection to an outside system, it seems more like an integration test to me (the test will fail if you can’t connect to the telephony system, a user is not configured as expected, I have some bug in my business logic, or there is an issue with the underlying libraries).
Should this test be labeled as an integration test? If so, how would I go about attempting to unit test methods like “retrieveUserInfo”? How do I properly segment these 2 types of tests?
Defining what a 'unit' is, is quite difficult. But if what you're testing is putting calls on external libraries that actually call to different systems, then you're definitely in the realm of integration testing.
What a unit is limited to is a bit subjective, but might be restricted to a class or public method on a class.
If you want to unit test a method that calls methods on an external dependency, then that's something you want to mock or stub (see Moq for a good mocking library).
I am having difficulties while trying to understand the purpose of mocking my WCF applications in unit tests. I have read this article Testing with mock objects and I believe I got the idea why we use mocking in standard application - it is better to test behaviour rather than implementation of the method. So with using Mock objects, I can test whether certain method called certain mock object, whether it changed some properties etc.
But while I was searching for some good ways how to test WCF, everyone was suggesting to use Mocking as well. The thing is, that I feel like I should test whether method (which is communication with service) is really able to reach the service and obtain result, that is satisfactory...which is not the case I will achieve using mock object.
Question:
Is using mock objects in my WCF app unit tests really intended to test only whether the method tried to call the OperationContract(method) exposed by service (while not expecting the real results)?
Or am I missing something?
The purpose of Unit Testing is not to test your application, but to make sure the code you've written is doing what is intended and subsequently let you know when you've made a simple coding goof. When it comes to testing for communication-based services, there are a dozen other factors, not the least of which being actual connectivity, that could affect your connection but not actually tell you anything useful about your code. Thus, you should rely on running debug runs of your application to test end-to-end functionality, and Unit Tests with those mocks to test the actual code functionality.
Will you miss something here and there? Yes, but the definition of good Unit Tests is such that you'll eventually have to touch them up when this happens.
I want to test my WCF classes (Integration testing) but I don't want to start them as WCF services.
Everything works well but in some cases I need to read IncomingMessageHeaders from OperationContext. I wonder if this can be done?
What I've learned to far is that I can create OperationContext and use it. But I'd need to create it via ChannelFactory which requires Binding (and then Endpoint). What I need (probably) is somehow make a local binding to my implementation class. Is this possible?
The best way to handle this is to use DI/IoC to abstract OperationContext out to an interface and then use a mocking framework like Moq or Rhino to implement that interface. When you test, your mocking framework will provide an instance of that new class in place of OperationContext. That completely removes your dependency on something external during testing.
The alternative is to make each WCF method a one-liner, calling a business logic layer, which you will be able to unit test without having to worry about WCF implementation details.
I'm not doing much new development right now, but a lot of refactoring of older C# subsystems whose original requirements no longer support new and I'll add unexpected requirements. I'm also now using Rhino Mocks and unit tests where possible (vs 2008).
The dilemma for me is that to make the methods testable and mockable, I need to define clear "contracts" using interfaces. However, if I do this, a lot of the global data that many of the classes use turns into tramp data, passed from method to method until it gets to its intended user; this looks ugly, and is against my sensibilities, but ... can be mocked. Making a mixed bag class with a lot of static global properties is a more attractive option but not Rhino testable. Is there a middle ground between the two? Testable but not too trampy? Pattern perhaps?
You should also understand that these applications run on an in-house corporate developed platform, so there are a lot of helper classes and services that are instantiated once per application, and then are used throughout the application, for example a database accessor helper class. Another example is using configuration files that are read once, and used throughout the application by different methods for various reasons.
Your thoughts appreciated.
What you might want to look at here is some form of the Service Locator Pattern. Make them classes find their own tramps.
Some other reasonable options would include wrapping up the bulk of the commonly used stuff in an "application context" class of some sort.
You also might wish to look into dependency injection if you haven't done so yet.
How are you supposed to unit test a web service in C# with Visual Studio 2008? When I generate a unit test it adds an actual reference to the web service class instead of a web reference. It sets the attributes specified in:
http://msdn.microsoft.com/en-us/library/ms243399(VS.80).aspx#TestingWebServiceLocally
Yet, it will complete without executing the test. I attempted to add the call to WebServiceHelper.TryUrlRedirection(...) but the call does not like the target since it inherits from WebService, not WebClientProtocol.
What I usually do is not test directly against the web-service, but to try and put as little code as possible in the service, and call a different class which does all the real work. Then I write unit tests for that other class. It turns out that class can sometimes be useful outside of the web-service context, so this way - you gain twice.
If you are writing a web service, try to put all logic in another (testable) layer. Each Web method should have a little code as possible. Then you will have little reason to test the web method directly because you can test the underlying layers.
[WebMethod]
public void DoSomething()
{
hander.DoSomething();
}
If you are consuming a web method, wrap the generated caller in a class wrapper, and implement an interface for the class wrapper. Then, anytime you need to call the web service, use the interface to call the method. You want to use the interface so as to make the class wrapper swappable during testing (using Rhino Mocks, Moq, or TypeMock).
You can add a service reference to your unit test project or generate your client stub and put the class in your unit test project.
I had problems with this as well, so i use this workaround:
http://techkn0w.wordpress.com/2009/07/01/unit-testing-an-asmx-web-service-in-visual-studio-2008/
Above my web method unit tests, I have the following:
// TODO: Ensure that the UrlToTest attribute specifies a URL to an ASP.NET page (for example,
// http://.../Default.aspx). This is necessary for the unit test to be executed on the web server,
// whether you are testing a page, web service, or a WCF service.
[HostType("ASP.NET")]
[UrlToTest("http://localhost/MyWebService")]
In addition to the usual:
[TestMethod()]
[DeploymentItem("MyWebService.dll")]
This code came about from using the Visual Studio 2008 Unit Test Wizard.
Know that there are two types of Web Service. Those you write yourself and want to test, and those that you consume. For the former, the above rules apply. However, I would say that sometimes I see developers testing against external web services. Logic dictates that a third party service is unreliable and therefore requires much more testing. In object-oriented programming, it is best to understand the separation of concern that Martin Fowler and the others all told us about. This means that we should not test systems external to our own.
However, I like to write wrapper classes to provide useful functionality against the services. For example, Bing Maps has a number of amazingly powerful functions. I write tests against these just to ensure that they give me the expected values. Although not extensive, the point of them is that if the web service dies for any reason (authentication key expires, etc) then I can be informed of it via the Test Server.