how to test WPF forms? - c#

I'm writing complex application where are server and client application, if i want to add some new window in my application i need to run server, then run client, then login click few buttons before i reach window which i right now developing, it's annoying and takes much time. So now i'm looking for some solution where i can run test which can run only my wpf form using mock for services (so i don't need running server and don't need to login), can click or fire events and check controls appear and act the way i want.
In this case i can save a lot of time because i dont need to waste time when i try to reach my form by running whole application where i need to use login, search bypass some validation forms and etc.
If there is already simple solution then it will be great.

Take a look at the MVVM pattern.
MVVM for WPF

Are you using any kind of dependency injection? It would be easy if so, you could simply create fake version of your heavy service using mocking framework with combination of #if-else directives. Somewhere in your application startup code:
ILoginService service;
#if DEBUG
service = A.Fake<ILoginService>();
// you could even set up your fakes to return logged user to
// automate logging in process:
var userFake = A.Fake<IUser>();
A.CallTo(() => service.LogIn(A<string>.Ignored)).Returns(userFake);
#else
service = new RealLoginService();
#endif
var myWindow = new MyWindow();
var viewModel = new ViewModel(service);
myWindow.DataContext = viewModel;
// ...
All you need is ViewModel (assuming you use such) being able to take ILoginService dependency. Then you can mock/fake it up to your liking.

Related

How to create a Bound Service in an Android app?

I am basically working on a Xamarin.Forms (cross platform) Project which uses Portable Class Library. And I know I cannot run background services from PCL, so I need to get into each platform individually for that. Now I'm stuck in android.
What I need to create is a bound service. So when my app starts, I have 2 buttons, Start and Stop (disabled). I click on start (start button becomes disabled and stop button enabled) it sends a message to my android platform using MessagingCenter to start the service using an Intent and Bind To it.
So I have this in my MainActivity.cs
MessagingCenter.Subscribe<StartAppBoundServiceMessage>(this,
"StartServiceMessage", message =>
{
Intent objXPathServiceIntent = new Intent(this, typeof(XPathService));
StartService(objXPathServiceIntent);
connection = new XPathServiceConnection(this);
BindService(objXPathServiceIntent, connection, Bind.AutoCreate);
});
StartAppBoundServiceMessage is a simple class in my PCL.
Now when I leave my app(using home button or back button or maybe a call comes), I want it to unbind from my service- but my service should still go on. That is why I have started my service using StartService(). But again when it is unbinding it should preserve somethings (like settings that are being used in the service) that had been set from my UI.
The next time when I come back my application should check if my service is running, if it is (it must bind to it again and let me make setting changes or stop the service by clicking on the stop button etc).
I have 2 questions:
I am confused on where I should UnBind when my app is leaving foreground, and where to Bind when coming back again. I know how to check if my service is running already, but i dont know where to check it. because back button calls onCreate and home button calls onResume.
How to preserve these settings in my service and put them back into my UI when I comeback.
PS: All my service methods will be called from my PCL project.
Note: The requirements are somewhat like a music player but the app is no where close to it.

Using IoC container in two C# apps with events

I have two projects in a Visual Studio solution where one is a console app and the other is a WPF app. Both have a composite root where a common bootstrapper is instantiated in each and registers some common types.
I'm trying to get the console app to subscribe to some events published by the WPF app. When a WPF window is moved, opened, or resized, the console app prints a string on the console.
The Bootstrapper class is in a separate class library with the following code:
public class Bootstrapper
{
public void Initialize()
{
var container = IocContainer.Instance.Container;
container.Register<IOrderRepository, SqlOrderRepository>(Lifestyle.Singleton);
container.Register<ILogger, FileLogger>(Lifestyle.Singleton);
container.Register<IEventPublisher, EventPublisher>(Lifestyle.Singleton);
container.Register<CancelOrderHandler>();
container.Register<IViewsIntegrationService, ViewsIntegrationService>(
Lifestyle.Singleton);
try
{
// Verify the container
container.Verify();
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
System.Console.ReadLine();
}
}
}
Both apps have this code in the composite root:
var bs = new Bootstrapper();
bs.Initialize();
The ViewsIntegrationService fires the events in the WPF app.
The Console app subscribes to the ViewsIntegrationService events.
When I run both applications, the console app does not receive the events and nothing prints on the console.
Is it because each of the apps use separate instances of the bootstrapper? Hence two sets of identical registrations? Or is this not working because of another reason?
Despite being 2 projects in the same Visual Studio solution, when compiled each one is an individual Windows executable program. These two programs will not automatically communicate with each other. If you need to transfer information from one program to the other, you will need to use some sort of communication channel such as TCP or MSMQ. See Send/Receive message To/From two running application.
Alternatively, you could make your "console application" into a class library (which when referenced from WPF will be part of the same application) and use a WPF window that looks like a console application window write out information.
Events and dependency injection only affect a single application, so neither are relevant in the case you are communicating across application boundaries.

Issue with windows service waiting for a named event, using EventWaitHandle.

I'm currently developing a windows service with c# and .net framework 4.5 to extend the functionality of an existing propietary application, this service blocks on an EventWaitHandleClass (msdn link) waiting for a named event signaled from the main application. Something like this:
bool boolWithFalse = false;
string eName = "notification_event";
string usr = Environment.UserDomainName + "\\" + Environment.UserName;
EventWaitHandleSecurity security = new EventWaitHandleSecurity(); //*
EventWaitHandleAccessRule rule = new EventWaitHandleAccessRule(usr, EventWaitHandleRights.Synchronize, AccessControlType.Allow);
security.AddAccessRule(rule);
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, eName, out boolWithFalse, security);
//... some non relevant code lines here
//This is where the it locks waiting for the named event
var w = EventWaitHandle.WaitAny(new[] { handle }, Timeout.Infinite);
*: EventWaitHandleSecurity MSDN
Now this works like a charm if i execute my program as a console application, i can easily catch events from the main application and handle them as i intend, BUT, when i install the application as a service it locks waiting for this same named event but never receive the signal. The service is set to run using the NT AUTHORITY\LOCALSERVICE account, i've already tried using my own account (wich the progam uses while running as a console application) and yet nothing happens.
If it helps the application that originates the signal is running under my own account. I appreciate any help as i'm a complete beginner developing desktop applications for windows.
You got lost in the security hoopla. Two problems. The first one is that somebody has to create the event and somebody else has to open it so both components share the same event object. One of them has to use the EventWaitHandle constructor, the other has to call the EventWaitHandle.OpenExisting() method. The normal way is for the service to create the event and for the UI program to open it.
Next problem is the event object visibility. Windows implements namespaces for named operating system objects, pretty similar to how you use namespaces in the C# language. The root namespace is named by the session. And a service runs in a different session than the user's desktop programs. To get the desktop session program to see the event created in the service session, you have to use a "global" event name. Which looks like this:
string eName = "Global\\notification_event";
Do be careful of how you name your globally visible named event. There's another programmer somewhere someday that thinks that "notification_event" is a good choice for a name. You don't want to meet him. A {guid} is a good name, you get one from Tools + Create GUID. It is unique in the known universe, possibly beyond.

Restart a WCF service hosted by a C# console application

I have a WCF service that is hosted on a c# console application. Is there a way to restart this service, preferably by calling an endpoint in the service itself (ex. myService.Restart()).
Thanks
I have to do something similar when I perform an automatic update of a remote WCF service. In your Restart() method, close the host:
try
{
host.Description.Endpoints.Where(x => !x.Address.ToString().EndsWith("MEX")).ForEach(endpoint => _log.InfoFormat("Closing {0}", endpoint.Address));
host.Close(TimeSpan.FromSeconds(5));
}
catch (Exception)
{
host.Abort();
}
I wait for my update to apply, and then after a success or failure, I re-open the host using the same code I used to start it in the first place.
If you just wanted to restart immediately, you could just call host.Open(), or you could set up a timer to call it, etc.
try
{
host.Open();
host.Description.Endpoints.Where(x => !x.Address.ToString().EndsWith("MEX")).ForEach(endpoint => _log.InfoFormat("Host opened at: {0}", endpoint.Address));
}
catch (Exception ex)
{
_log.Error("Unable to open host.", ex);
}
To answer my question, I have solved the problem by doing the following:
Separating the code that loads the DLL files from the WCF service code into another class library project
Create an interface with the same method signatures as the ones that load DLL files in the new project (this interface is used by both projects now)
In the web service, load the other project in a new application domain. This way the DLL files are locked by the new application domain not the default.
If I want to update my nunit DLL files now, all I have to do is unload the application domain from the web service, update the files and finally create a new application domain.
AppDomain remoteDomain = AppDomain.CreateDomain("New Domain");
IClass1 class1 = (IClass1)remoteDomain.CreateInstanceFromAndUnwrap(
"Test1.dll", "Test1.Class1");
Note: IClass1 is the common interface between the projects.
you definitely are not going to be able to 'restart' a faulted service from calling that same service itself. In theory you could host 2 services in the same process. put the one you want to be 'restartable' in a public static variable and restart it within the other service. The problem would be restarting the restarter service if it faults... :) and you definitely want 'administrator-like' restrictions on your restarter service so unauthorized users can't do it.
It's a bit kludgy, but I suppose you could expose a callback on your service that the host could attach to and take appropriate action when it's triggered. That would give your host the ability to decide what a "restart" really means and how it needs to be executed. More importantly, it lets your decide whether it should do something extreme like spawn off a watcher process and then off itself or gracefully trash and reinstantiate your service (preferable).
Mmmmmm... kludge....
You cannot ask a service to restart itself. Consider a windows service (a service hosted in windows provided container) which has a RESTART functionality. Here RESTART functionality is provided not by the service but by the container. The container controls how to stop the service and start it.
Similarly in your case, you should try to look out for options if your container can provide the functionality you need. Since you want to control it remotely, the container should also be available remotely, which cannot be possible if the container is a console application. Instead it has to be another web service or web application.

What is the accepted pattern for an application that can be run as a service or as a console application

I have a project that is deployed to production as a windows service. However for local development purposes it would be useful to run it as a console application. At the moment I have a class Called ReportingHost that provides my core functionality, And a class called ReportingServiceHost that inherits from ServiceBase and allows me to run the application as a service. There is also a program class with a main method that calls ServiceBase.Run on my ReportingServiceHost.
I think I need to write a ReportingConsoleHost class that allows me to run the functionality in a console. Then I need to modify my Main to react to a command line switch and choose one or the other. These are the two bits I am having trouble with.
I have had a look at this and attempted to use that code but my app exits immediately, it doesn't show a console window and it doesn't wait for Enter before closing.
Part of the problem is that I dont have a deep understanding of how these things work. a definitive pattern for splitting my functionality, my two different ways of running that functionality, and a main method that chooses one of these ways based on a command line argument is what I am hoping to achieve.
I suspect your test project was configured as a windows exe, not a console exe. With a windows exe Console.ReadLine will return immediately.
To have a console exe that works both as a service and at the command line, start it as a service project (in Visual Studio) - and add a check on Environment.UserInteractive - i.e.
static void Main() {
if(Environment.UserInteractive) {
// code that starts the listener and waits on ReadLine
} else {
// run the service code that the VS template injected
}
}
You can of course also use a command line switch. I have example on microsoft.public.dotnet.languages.csharp that acts as:
an installer / uninstaller
a service
a console-mode app
depending on the switches
I have done this before by implementing a normal Windows Service (by deriving from ServiceBase), but putting a check in the main method to check for a command line argument.
If the args contain /console, start the console version, otherwise start the service.
Something like this:
internal class MyService : ServiceBase
{
internal static void Main(string[] args)
{
if (args.Length == 0)
{
// run as a service....
ServiceBase[] servicesToRun = new ServiceBase[] {new MyService()};
Run(servicesToRun);
}
else
{
// run as a console application....
}
}
}
My advise? Put all your logic for your service in a separate assembly. (A class library or DLL.) Then create one project as service which references your class library and puts the code to use as services. Create a second console project which also references your class library but which will make it available as a console application.
You would end up with three different projects in your solution but it does allow you to keep things separate. Actually, this would make it possible to extend your service in several other shapes too. You could, for example, create a 4th project as a web service and thus call your service from a web browser on a client system. Because the software logic is separated from the usage logic, you gain lots of control over it.
Be aware that a service will possibly run with more limitations than a console application. In general, services don't have network access by default, don't have a monitor assigned to them to display error messages and in general run with a limited user account or system account. Your service might work as a console yet fail as a service because of this.
There are already two good answers above - but I thought I'd post a link to Brian Noyes' Debuggable Self-Host Windows Service Project blog post - it talks about WCF but should apply to any 'Windows Service'.
The best thing is the sample code - if you can't figure out where the above examples 'fit', grab the complete project and see how it works. Thanks Brian!

Categories

Resources