Recommended patterns for unit testing web services - wcf

We are about to begin architecting a service oriented framework (SOA) which will certainly involve a high number of of granular web services (REST in WCF). We've been quite disciplined in unit testing our client and server-side code base, however we don't have much of any experience in unit testing web services. We're really looking for guidance as to where the tests should be written and recommendations on what approach to use when unit testing our services.
Should we write tests that make http requests and assert that the responses are what they should be? Should we focus on just testing the internal logic of the service methods themselves and not worry about testing the actual requests? Or should we do both? Are there any other recommendations for what we should be testing?
We're really looking for some explanation and guidance and would truly appreciate any advice we can get.

I have found testing web services, specifically WCF client and server, useful on top of regular unit testing in the following scenarios:
Acceptance testing where you want to black box test your whole service and poke things in at the extremities.
Testing a specific WCF wire up, extension, behavior, etc.
Testing that your interface and your data members are setup correctly.
Most of the time I try to use a very basic setup with basic http and wire everything up in the code. Unless I am Integration or Acceptance testing I don't test the client against the server, instead I mock one of them so that I can test the other in isolation. Below are examples of how I test WCF clients and services:
public static ServiceHost CreateServiceHost<TServiceToHost>(TServiceToHost serviceToHost, Uri baseAddress, string endpointAddress)
{
var serviceHost = new ServiceHost(serviceToHost, new[] { baseAddress });
serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
serviceHost.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;
serviceHost.AddServiceEndpoint(typeof(TServiceToHost), new BasicHttpBinding(), endpointAddress);
return serviceHost;
}
//Testing Service
[TestFixture]
class TestService
{
private ServiceHost myServiceUnderTestHost;
private ChannelFactory<IMyServiceUnderTest> myServiceUnderTestProxyFactory;
[SetUp]
public void SetUp()
{
IMyServiceUnderTest myServiceUnderTest = new MyServiceUnderTest();
myServiceUnderTestHost = CreateServiceHost<IMyServiceUnderTest>(myServiceUnderTest, new Uri("http://localhost:12345"), "ServiceEndPoint");
myServiceUnderTestHost.Open();
myServiceUnderTestProxyFactory = new ChannelFactory<IMyServiceUnderTest>(new BasicHttpBinding(), new EndpointAddress("http://localhost:12345/ServiceEndPoint"));
}
[TearDown]
public void TearDown()
{
myServiceUnderTestProxyFactory.Close();
myServiceUnderTestHost.Close();
}
[Test]
public void SomeTest()
{
IMyServiceUnderTest serviceProxy = myServiceUnderTestProxyFactory.CreateChannel();
serviceProxy.SomeMethodCall();
}
}
//Testing Client
[TestFixture]
class TestService
{
private ServiceHost myMockedServiceUnderTestHost;
private IMyServiceUnderTest myMockedServiceUnderTest;
[SetUp]
public void SetUp()
{
myMockedServiceUnderTest = Substitute.For<IMyServiceUnderTest>(); //Using nsubstitute
myServiceUnderTestHost = CreateServiceHost<IMyServiceUnderTest>(myMockedServiceUnderTest, new Uri("http://localhost:12345"), "ServiceEndPoint");
myServiceUnderTestHost.Open();
}
[TearDown]
public void TearDown()
{
myServiceUnderTestHost.Close();
}
[Test]
public void SomeTest()
{
//Create client and invoke methods that will call service
//Will need some way of configuring the binding
var client = new myClientUnderTest();
client.DoWork();
//Assert that method was called on the server
myMockedServiceUnderTest.Recieved().SomeMethodCall();
}
}
NOTE
I had forgot to mention that if you want to mock a WCF service using anything that uses castles dynamic proxy then you will need to prevent the ServiceContractAttribute from being copied to the mock. I have a blog post on this but basically you register the attribute as one to prevent from replication before you create the mock.
Castle.DynamicProxy.Generators.AttributesToAvoidReplicating
.Add<ServiceContractAttribute>();

Well basically I think that you need to have a two part test strategy.
The first part would be true unit tests, which would involve testing the classes completely independent of any web request ... as the main definition of a unit test is one that runs without the need of extra environments or setups other than the ones in the test itself.
So you would create unit test projects, in which you would instantiate the code classes of your WCF services to make sure the logic is correct, in much the same way that you test the rest of your classes.
The second part would be a set of integration tests, which would test your application in an end-to-end fashion. Of course, here you need the whole enchilada, web server, database, and so forth.
This way you know that your logic is accurate and also that your application works.

Related

Is pact consumer test for generating contract json files only?

Is pact consumer test for generating contract json files?
I am studing pact and got qurioused about what is the consumer test for? It tests the response that the test class defindes.
In my code below. I defined a response with 200 and simple body, then Test it calling by mockProvider. seems useless. Anybody please give me some guides.
public class PactTest {
#Rule
public PactProviderRuleMk2 mockProvider
= new PactProviderRuleMk2("test-provider", "localhost", 8017, this);
#Pact(consumer = "test-consumer")
public RequestResponsePact createPact(PactDslWithProvider builder){
Map<String, String> headers = new HashMap<>();
return builder
.given("test Get")
.uponReceiving("GET REQUEST")
.path("/pact")
.method("GET")
.willRespondWith()
.status(200)
.headers(headers)
.body("{\"condition\": true, \"name\":\"tom\"}")
.toPact();
}
#Test
#PactVerification
public void givenGet_whenSendRequest_shouldReturn200withProperHeaderAndBody() {
ResponseEntity<String> res = new RestTemplate()
.getForEntity(mockProvider.getUrl()+"/pact", String.class);
assertThat(res.getStatusCode().value()).isEqualTo(200);
}
}
Short answer - no.
Calling the mock API in the test independent of your actual consumer code is worthless (as you imply), because it is a self-fulfilling prophecy. Pact is designed to test the collaborating service on the Consumer side; the adapter code that makes the call to the Provider.
Typically, this call will pass through things like data-access layers and other intermediates. Your Pact tests would use a service that uses these, and the benefit is that the contract gets defined through this process, that is guaranteed to be up-to-date with consumer needs, because it is generated via your code.
We've just updated the docs today, perhaps that helps.

WCF Task based asynchronous callback

I have created WCF service in VS2015:
[ServiceContract(CallbackContract = typeof(IMyCallback))]
public interface IMyService { }
IMyCallback looks like:
[ServiceContract]
public interface IMyCallback {
[OperationContract]
Task<string> OnServerEvent(UserAppEventData evData);
I've built the server, run it, then added service reference (by right click on solution explorer).
The client object is defined as
[CallbackBehaviorAttribute(
ConcurrencyMode = ConcurrencyMode.Reentrant,
IncludeExceptionDetailInFaults = true,
UseSynchronizationContext = true,
ValidateMustUnderstand = true
)]
public class QMyClient : IMyCallback { }
Automatically generated interface implementation made method in sync manner:
public string OnServerEvent(UserAppEventData evData) { }
This code does't work (and isn't asynchronous) and hangs client at OnServerEvent.
When I changed code manuallly to
public async Task<string> OnServerEvent(UserAppEventData evData)
and have done the same in auto generated "service references\...\Reference.cs, all works fine. But I don't want to change Referenece.cs every time I'm updating Service Reference.
Is there any method to force "Update Service Reference" make TBA OperationContractAttribute on callback?
At ordinary WCF service direction everything works OK, VS generates task based operations.
By default the service reference you've added to solution doesn't have asynchronous operations, but you can enable them and decide which option you use for your async methods - task-based or old-fashion asynchronous. This option is available in Advanced settings for service reference.
If you're using a svcutil tool, it will create the task-based methods by default, however, you can change that behavior by some flags like /async or /syncOnly.
What #VMAtm suggested will work out just fine.
I think, you could also use ChannelFactory for this scenario. It is very flexible and you can then await on the service operations from client side. Additional benefit, you don't need to modify client when there are these kind of changes on service side.
Something like:
var channelFactory = new ChannelFactory<IService>(
"WSHttpBinding_IService" // endpoint name
);
IService channel = channelFactory.CreateChannel();
string result = await channel.OnServerEvent();
Console.WriteLine(result);
Please note that for this scenario, you will have to import common interface library to client side as dll because then it will need to know about contracts and data contracts.

How to run XUnit test on both self-host & production webapi service?

I'd like to write a test for my ASP.NET WebApi service and run it against a self-hosted service and the live web hosted service. I imagine that this can be done with a test fixture, but I'm not sure how to set it up. Does anyone know of an example of using a configurable test fixture so that you can pass a parameter to Xunit to choose a self hosted fixture or a web hosted fixture?
Here is how it works with latest xUnit 2.0 beta.
Create a fixture:
public class SelfHostFixture : IDisposable {
public static string HostBaseAddress { get; private set; }
HttpSelfHostServer server;
HttpSelfHostConfiguration config;
static SelfHostFixture() {
HostBaseAddress = ConfigurationManager.AppSettings["HostBaseAddress"]; // HttpClient in your tests will need to use same base address
if (!HostBaseAddress.EndsWith("/"))
HostBaseAddress += "/";
}
public SelfHostFixture() {
if (/*your condition to check if running against live*/) {
config = new HttpSelfHostConfiguration(HostBaseAddress);
WebApiConfig.Register(config); // init your web api application
var server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();
}
}
public void Dispose() {
if (server != null) {
server.CloseAsync().Wait();
server.Dispose();
server = null;
config.Dispose();
config = null;
}
}
}
Then define a collection that will use that fixture. Collections are the new concept to group tests in xUnit 2.
[CollectionDefinition("SelfHostCollection")]
public class SelfHostCollection : ICollectionFixture<SelfHostFixture> {}
It serves as just a marker so has no implementation.
Now, mark tests that rely on your host to be in that collection:
[Collection("SelfHostCollection")]
public class MyController1Test {}
[Collection("SelfHostCollection")]
public class MyController4Test {}
The runner will create a single instance of your fixture when running any test from within MyController1Test and MyController4Test ensuring that your server is initiated only once per collection.
I would recommend to use the In-Memory Server for testing your controllers, so you don't need to spin up a self-host in your unit tests.
http://blogs.msdn.com/b/youssefm/archive/2013/01/28/writing-tests-for-an-asp-net-webapi-service.aspx

Issue with mocking WCF service

I have some problems with mocking WCF services:
1) I declare a class with empty methods which only implements my service interface:
public class MyFakeService : IMyService {
...
public virtual MyResult GetResult(MyResponse response){
throw new NotImplementedException();
};
}
2) I have the MyResponse class:
public class MyResponse {
public long myField;
}
3) I create a mock of the service class and a service host to host this fake service:
myFakeService = mocks.StrictMock<MyFakeService>();
ServiceHost host = new ServiceHost(myFakeService);
(here I have ommited the endpoint configuration etc.)
4) And now I try to test my client. The client.GetSomethingFromService() method exactly calls the GetResult(MyResponse) method of the service.
With.Mocks(mocks)
.Expecting(() => Expect
.Call(myFakeService.GetResult(null))
.IgnoreArguments()
.Constraints(PublicField.Value("myField", 777))
.Return(new MyResult()))
.Verify(() => myClient.GetSomethingFromService());
The issue is that if something wrong in the service, I can only see something like this:
System.ServiceModel.CommunicationObjectFaultedException:
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used
for communication because it is in the Faulted state.
How do I know what exactly wrong? Maybe arguments constraints verification failed or something else...?
Thanks.
Firstly, avoid using strict mocks. They're a bad practice because they make your tests too brittle.
Secondly if you're testing a WCF service you don't need to spin up a ServiceHost since you'll then be doing an integration test. You're just wanting to test the logic of your service, not the WCF infrastructure.
For a run through of how to use RhinoMocks and WCF services have a look at my blog post on unit testing WCF services

RhinoMock help: Mocking WCF service

I'm trying to use RhinoMock for mocking out a wcf service.
Say I have the following service:
[OperationContract]
List<User> SearchUsers(UserSearchFilter filter);
Adding this service with Visual Studio will generate a proxy, and that proxy has a Interface like:
public interface ResourceService {
System.IAsyncResult BeginSearchUsers(UserSearchFilter filter, System.AsyncCallback callback, object asyncState);
ObservableCollection<User> EndSearchUsers(System.IAsyncResult result);
}
Then I create a ViewModel that uses this service, like this:
private ResourceService service;
public ViewModelBase(ResourceService serv)
{
service = serv;
var filter = new UserSearchFilter();
service.BeginSearchUsers(filter, a =>
{
this.Users = service.EndSearchUsers(a);
}, null);
}
Then comes the question. How do I mock this service using RhinoMock?
[TestMethod]
public void UserGetsPopulatedOnCreationOfViewModel()
{
// Is stub the right thing to use?
ResourceService serv = MockRepository.GenerateStub<ResourceService>();
// Do some setup... Don't know how?
var vm = new ViewModel(serv);
Assert.IsTrue(vm.Users.Count > 0);
}
I be really happy if someone could help me with the correct usage of RhinoMock
(Note: I'm using Silverlight, but I don't think that would change the way RhinoMock is used)
Thanks a lot!
I wrote a 4-part article all about testing apps that use WCF services.
Part 2 talks about mocking out the service using RhinoMocks
Part 3 talks about mocking out an asynchronous service using Moq
Note that part 3 can be translated over to RhinoMocks very easily. I was just trying to show different mocking frameworks, and that the technique did not rely on the mocking framework.
Hope it helps!
EDIT
So, in Rhino Mocks, you do this in the setup:
mockService.YourEvent += null;
IEventRaiser loadRaiser = LastCall.IgnoreArguments().GetEventRaiser();
Then in the playback, you do this:
loadRaiser.Raise(mockService, CreateEventArgs());
You can find more info on mocking events in Rhino in Phil Haack's blog post.
I would create interface that service would implement (IResourceService).
Then on Silverlight side create custom implementation of IResourceService that calls WCF service itself.
RihnoMock would create the stub for IResourceService interface and not for WCF service.
It's very easy to do using Prism 2, you can read more here:
http://mokosh.co.uk/post/2009/04/19/prism-2-wpf-and-silverlight-services/