Unit Testing WCF Service is launching - c#

I'm new to WCF. I've created a basic service and engineer tested it with the debugger and WCFTestClient. I've never written my own WCF client. Now I need to build unit tests for the service.
My classes:
IXService
CXService
CServiceLauncher
(Yes, I know the C prefix does not meet current standards, but it is required by my client's standards.)
My service functionality can be tested directly against XService, but I need to test CServiceLauncher as well. All I want to do is connect to a URI and discover if there is a service running there and what methods it offers.
Other questions I read:
AddressAccessDeniedException "Your process does not have access rights to this namespace" when Unit testing WCF service -
starts service host in unit test
WCF Unit Test - recommends
hosting the service in unit test, makes a vague reference to
connecting to service via HTTP
WCF MSMQ Unit testing -
references MSMQ, which is more detailed than I need
Unit test WCF method - I never knew I could auto generate tests, but the system isn't smart enough to know what to assert.
Test outline:
public void StartUiTest()
{
Uri baseAddress = new Uri("http://localhost:8080/MyService");
string soapAddress = "soap";
IUserInterface target = new CServiceLauncher(baseAddress, soapAddress);
try
{
Assert.AreEqual(true, target.StartUi());
/// #todo Assert.IsTrue(serviceIsRunning);
/// #todo Assert.IsTrue(service.ExposedMethods.Count() > 4);
Assert.Inconclusive("This tells us nothing about the service");
}
finally
{
target.StopUi();
}
}

I just needed to build a simple client.
Reference:
http://webbeyond.blogspot.com/2012/11/wcf-simple-wcf-client-example.html
Add Service Reference to test project
Add to test file:
using System.ServiceModel;
using MyTests.ServiceReferenceNamespace;
Code inside try is now:
Assert.AreEqual(true, target.StartUi());
XServiceClient client = new XServiceClient();
client.GetSessionID();
Assert.AreEqual(CommunicationState.Opened, client.State, "Wrong communication state after first call");

It's not a real answer so please take it easy.
I have been trying to do similar things and what I have learnt that integration testing is difficult. It is difficult because there are many hidden tasks that you need to do, such as:
Make sure you can run the tests regularly
Make sure integration tests can run on the test environment
Maintain different config files, as your environment will be different from the test one
Configure the thing that would automate running of integration tests (CI)
Pray there will be no changes to the paths, test environment, config, hosting platforms etc
Fight security permissions, as usually test thing is not able to host WCF services without admin permissions
Maintain your test harness
To me, this was huge headache and little gain. Don't get me wrong, integration testing is a positive thing, it just requires a lot of time to develop and support.
What have I learnt? Is that do not bother with integration testing of WCF services. Instead I write a lot of unit-tests, to test the contract, state and behaviour. By covering those, I can become sure in a quality of software. And I fight integration of WCF during deployment. This is usually a single battle to configure environment or VM and then next time, deployment goes nice and smooth in an (semi-)automated manner.
Most people would also automate deployment with Chef and alike, those tools can fully configure environment and deploy WCF service.

Related

Azure pipelines bind to localhost for tests

I am trying to run integration tests in Azure Pipelines by spinning up a web server and hitting it with HTTP requests in a different process.
The error I received is
System.AggregateException : One or more errors occurred. (Failed to bind to address http://127.0.0.1:49159: address already in use.)
The code that seems to generate the error is
var builder = new WebHostBuilder()
.UseUrls("http://localhost:49159")
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.Configure(app =>
{
app.Run(handler);
})
.Build();
builder.Start();
I have tried a bunch of different ports so assume that you just cannot bind to localhost on Azure Pipelines.
Does anyone know if there is a way to achieve what I am trying to do with Azure Pipelines?
Any help would be massively appreciated!
Yes, it's definitely possible. Maybe you're starting the web host more than once and not detroying it (i.e. for each test fixture, etc.)?
In general, these are some of possible ways to run integration tests in the pipeline:
If your integration tests are written in .Net, then consider using WebApplicationFactory to run server & tests in a single process.
If you use different tools for integration tests,
node's start-server-and-test module does a great job of starting your server, waiting for it to be ready and then executing tests (you can use it for .Net projects as well). Here's a sample pipeline for .Net project.

C# Windows service won't start: "Cannot start service from command line or debugger"

Even though there are similar questions, I couldn't find any that solves mine. I have a simple program that runs as a service and I want to start it programatically. It's as simple as this:
private static void StartService()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(ServicesToRun);
}
As expected, I can't just start my service without installing it. Windows gives me the following error message:
Cannot start service from command line or debugger. A windows service must first be installed using installutil.exe and then started with service explorer, Windows services administrative tool or NET start.
So far so good. So I went there and did just as the docs says:
installutil <my_project>.exe
The installation was successful and I can even start my service from Service Manager or net start. The only problem is: when I debug my application (via F5), Windows keeps showing me the exact same message: Cannot start service (...).
I've found a solution here that uses this:
public void onDebug()
{
OnStart(null);
}
Which allows me to run and debug my application normally, but I actually need it to run as a service and Windows refuses to start that way. Is there anything I'm missing?
It is not in your power to just start a Service like a normal programm. The Service must be registered with and started by the Service manager. That is one of the (many) rules of Windows services. And you have to repeat that for every new build.
As this and other Service related rules (no interactive sessions) can make developing them a Pain, a common approach is to develop them using a console application. I could not find my ideal example, but I found something like it:
https://alastaircrabtree.com/how-to-run-a-dotnet-windows-service-as-a-console-app/
Of course a better longterm plan might be to stop using Services alltogether and switch over to the Windows Task Scheduler. It depends heavily on what exactly you need this code to be able to do in practice.

Is it possible to test WCF throttling behaviour through Wcftest client?

Is it possible to test WCF throttling behaviour through Wcftest client?
If Yes then How?
I have a code below for ServiceHost
ServiceThrottlingBehavior stb = _servicehost.Description.Behaviors.Find<ServiceThrottlingBehavior>();
if (stb == null)
{
stb = new ServiceThrottlingBehavior();
stb.MaxConcurrentCalls = 1;
stb.MaxConcurrentInstances = 1;
stb.MaxConcurrentSessions = 1;
_servicehost.Description.Behaviors.Add(stb);
}
My service has a method such as:
public string ThrottlingCheck()
{
Thread.Sleep(new TimeSpan(0, 0, 0, 5, 0));//5 seconds
return "Invoke Complete";
}
In the event that you are using “web” bindings, you could use the open-source soapUI/loadUI test tools.
SoapUI is a free and open source cross-platform Functional Testing solution. With an easy-to-use graphical interface, and enterprise-class features, SoapUI allows you to easily and rapidly create and execute automated functional, regression, compliance, and load tests.
Reference:
http://www.soapui.org/
http://www.soapui.org/Load-Testing/using-loadui-for-loadtesting.html
As your request is taking 5 seconds, you can easily test this by invoking two operations at the same time by using two WCF Test Client or by opening two tabs in the same WCF client.
An integration test is certainly a better choice to check this behavior.
In addition, if your want to check that the behavior is really applied to your service, you could use WCF diagnostics such as WCF counters, especially "Percent of Max Concurrent XXX".
No, it is not possible using WCF Test Client. If you have Visual Studio Ultimate you can use load tests/performance tests to test the throttling.
http://blogs.msdn.com/b/rickrain/archive/2009/06/26/wcf-instancing-concurrency-and-throttling-part-3.aspx?Redirected=true
If you company has a copy of LoadRunner (hp product), you'll be able to build up enough fake transaction to actually test throttling.
In our case, we actually built a multi-instance, multi-threaded program to slam our web service with 1000+ concurrent (fake) users, each uploading 40 files. It was only then that we were able to see the throttling begin to take effect.
BTW, we tried a bunch of different combinations to see if we could tweek the settings and increase the performance, but in the end, the fastest we were able to get our web service running was under the default settings for throttling ... in other words, no throttling at all, just letting WCF manage the traffic and queue. Weird, huh?

Keep C# application running

I'm building a Windows Service that uses FileSystemWatcher, and runs in the background.
I don't want to keep on uninstalling and installing the service every time I want to debug, so would like to do most of my development in a normal program before moving it into a service. But I'm quite new to this, and when I run it, it just runs through the block and exits.
What would be a good way to keep the program running?
http://einaregilsson.com/run-windows-service-as-a-console-program/
I've used this before to debug my service as a Console application based on whether its running in an interactive user environment.
public partial class DemoService : ServiceBase
{
static void Main(string[] args)
{
DemoService service = new DemoService();
if (Environment.UserInteractive)
{
service.OnStart(args);
Console.WriteLine("Press any key to stop program");
Console.Read();
service.OnStop();
}
else
{
ServiceBase.Run(service);
}
}
while (true)
{
// Execute your program's functionality here.
}
I wrote a 7 part series a while ago titled: Building a Windows Service. It covers all the intricacies of building services, making them friendly to debug, and self-installing.
The basic feature set I was looking for was as follows:
Building a service that can also be used from the console
Proper event logging of service startup/shutdown and other activities
Allowing multiple instances by using command-line arguments
Self installation of service and event log
Proper event logging of service exceptions and errors
Controlling of start-up, shutdown and restart options
Handling custom service commands, power, and session events
Customizing service security and access control
The final result was a Visual Studio project template that creates a working service, complete with all of the above, in a single step. It's been a great time saver for me.
see Building a Windows Service – Part 7: Finishing touches for a link to the project template and install instructions.
Here’s documentation from MSDN # http://msdn.microsoft.com/en-us/library/7a50syb3(v=vs.80).aspx?ppud=4 . I have tried it before and it works under .NET Framework 3.x. I could not find my descriptive notes on it, at the moment.
Use the pragma #If DEBUG for debugging purposes like console outputs. Another is using the Debug object.
If you have any trouble with this, say so. I may be able to find my notes or make a Windows Service app myself, just to see if the steps on MSDN still work.

Can a WebServiceHost be changed to avoid the use of HttpListener?

I am looking for a way to use a WCF WebServiceHost without having to rely on the HttpListener class and it's associated permission problems (see this question for details).
I'm working on a application which communicates locally with another (third-party) application via their REST API.
At the moment we are using WCF as an embedded HTTP server. We create a WebServiceHost as follows:
String hostPath = "http://localhost:" + portNo;
WebServiceHost host = new WebServiceHost(typeof(IntegrationService), new Uri(hostPath));
// create a webhttpbinding for rest/pox and enable cookie support for session management
WebHttpBinding webHttpBinding = new WebHttpBinding();
webHttpBinding.AllowCookies = true;
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IIntegrationService), webHttpBinding, "");
host.Open()
ChannelFactory<IIntegrationService> cf = new ChannelFactory<IIntegrationService>(webHttpBinding, hostPath);
IIntegrationService channel = cf.CreateChannel();
Everything works nicely as long as our application is run as administrator. If we run our application on a machine without administrative privileges the host.Open() will throw an HttpListenerException with ErrorCode == 5 (ERROR_ACCESS_DENIED).
We can get around the problem by running httpcfg.exe from the command line but this is a one-click desktop application and that's not really as long term solution for us.
We could ditch WCF and write our own HTTP server but I'd like to avoid that if possible.
What's the easiest way to replace HttpListener with a standard TCP socket while still using all of the remaining HTTP scaffolding that WCF provides?
Your problem is not related to HttpListener.
Your problem is:
* You have a oneClick application with limited permissions that
* Tries to open a Server port.
This is a contradiction. An untrusted limited permission application should NOT OPEN A SERVER PORT. This is why this is not allowed per definition.
Have you tried opening a normal socket port? It should not work either.
In general, limited trust end user applications should not host a web service ;)
That said, I ahve been in a similar situation trying to use WCF in a driver communication scenario - thank heaven my application runs with full permission.
You can easily compose your own stack via CustomBinding, using the higher level protocol stuff "as is", and rolling your own version of HttpTransport that isn't backed by HttpListener or IIS. Do-able, sure, but it's a lot of work. Take the existing HttpTransport bits apart with Reflector- there are a LOT of moving parts in there. You could probably hack up a simple PoC over Socket in a day or two if you don't need anything fancy like HTTPS or chunking, but making it robust will be tricky. Here's a good wrapup of a bunch of resources (may be a bit dated now).
You could also look at ripping apart enough of Cassini to make it hostable in your app, and loading the WCF pipeline in there (via .svc files and the service activation handler)- it'd require writing very little new code that way, but still give you a fairly robust and tested webserver.

Categories