C# wpf UnitTesting viewmodels - c#

I'm trying to unit test my viewmodels in a wpf application. I have a command in my viewmodel which executes a method containing a confirmation dialog. I need to run all unit tests, so that each time opening these dialogs it requires manual confirmation.
The question I have is there any way i can programmatically know which method have confirmation dialog and programmatically click "Ok" or "Cancel"?

The best solution to this is probably not to try to click Ok or Cancel programmatically, but to prevent the creation of the dialogs while running the unit tests.
To do this, you need an abstraction for getting a user confirmation, something like this:
public interface IUserConfirmation
{
bool Confirm(string title, string message);
}
In the Execute-method of your command, you only use this abstraction instead of actually showing a dialog:
public class ViewModel
{
private void MyCommandExecuted(object parameter)
{
if (this.confirmation.Confirm("Please confirm", "Are you sure you want to ...?")
{
...
}
}
Now you create two implementations of this interface: One which actually shows a dialog to the user and another one which simply returns a preconfigured value. In your main application, you use the "real" dialog implementation and in your unit tests you use the "fake" implementation.
In order to do that, you need to be able to "inject" different implementations in your ViewModel, for example via the constructor:
public ViewModel(IUserConfirmation confirmation)
{
if (confirmation == null)
throw new ArgumentNullException("confirmation");
this.confirmation = confirmation;
}
private readonly IUserConfirmation confirmation;
This is actually a well-known pattern called "dependency injection". There are frameworks available which can help you with the creation of objects, but for simple cases like this one they're not necessary.
Here's how the two implementations could look like:
public class MessageBoxUserConfirmation : IUserConfirmation
{
public bool Confirm(string title, string message)
{
return MessageBox.Show(title, message) == true;
}
}
public class TestUserConfirmation: IUserConfirmation
{
public bool Result { get; set; }
public bool Confirm(string title, string message)
{
return this.Result;
}
}
In your unit test, you use it like this:
var confirmation = new TestConfirmation();
var viewModel = new ViewModel(confirmation);
// simulate a user clicking "Cancel"
confirmation.Result = false;
viewModel.MyCommand.Execute(...);
// verify that nothing happened
There are also frameworks for creating these fake implementations without having to write your own classes all the time, but again, for simple cases like that you probably won't need them.

Related

Unit Testing ICommand and Methods

I have developed an WPF application using MVVM as a architecture and am writing some unit tests as part of this. In my view I have a button that is bound to a property in the ViewModel which can be seen below.
ViewModel
public ICommand MoreInfoCommand
{
get
{
if (_moreInfoCommand == null)
{
_moreInfoCommand = new RelayCommand(parameter => OpenLink());
}
return _moreInfoCommand;
}
}
private void OpenLink()
{
try
{
Process.Start("https://www.google.com/");
}
catch
{
// catch error...
}
}
In my unit testing I have created the following unit test:
UnitTest
[Description("Test MoreInfoCommand")]
[TestMethod]
public void TestMoreInfoCommand()
{
viewModel vm = new viewModel();
Assert.IsTrue(vm.MoreInfoCommand.CanExecute(null));
}
Currently this tests the the property to see if when the button is clicked in the UI the relevant method can be executed. This passes as the conditions are met, however its my understanding I need to test the functionality as well. With this in mind how do I, for example tests that the correct functionality occurs when the button is clicked. I.e how to test what occurs when the ICommand MoreInfoCommand is executed as a result of button click in the UI.
I know private methods can be tested directly, but should in my unit testing I be checking the functionality as well and if so, how can I do this.
Thanks in advance.
Your view model isn't really testable. If you want to it to be, you should replace the call to the static Process.Start method with a call to a method of a interface that you inject the view model with:
public ViewModel(IProcessLoader processLoader) =>
_processLoader = processLoader;
//...
private void OpenLink()
{
try
{
_processLoader.Start("https://www.google.com/");
}
catch
{
// catch error...
}
}
You could then mock the interface in your unit test, for example using a mocking framwork like Moq:
[TestMethod]
public void TestMoreInfoCommand()
{
//Arrange
Mock<IProcessLoader> processLoader = new Mock<IProcessLoader>();
viewModel vm = new viewModel(processLoader.Object);
ICommand command = vm.MoreInfoCommand;
//Act
command.Execute(null);
//Assert
processLoader.Verify(x => x.Start(It.IsAny<string>()));
}
In the real app, you would implement the interface as a wrapper around Process.Start:
public interface IProcessLoader
{
void Start(string s);
}
public class ProcessLoader : IProcessLoader
{
public void Start(string s) => Process.Start(s);
}
It's important to realize that you should only verify that the method is called from the view model. A unit test against the view model class should not test the functionality of the Process class. The resposibility of the view model ends when Start has been called.
.NET and the underlying OS is responsible for what the Process class actually does. You should not test this but only your own code.
vm.MoreInfoCommand.CanExecute(null) would only call the canExecute method in your RelayCommand, but you did not provide any. CanExecute tells nothing about whether OpenLink would perform successfully or not.
Although I am no unit test specialist, if your code real looks like this, I doubt if it's worth to write a unit test for it in the first place, because it is so very simple.
As the comment from user auburg states, you can check, whether the process starts, although the process's name would depend on which browser was the standard browser. Also, you would have to wait for some time for the process to start. And maybe there was a process with the same name already running, lots of chances for trouble.
If you really want, you can check, if one of the well known mocking frameworks, e.g. Moq or Rhino Mocks, is able to mock away Process.Start.

Separation of the logic of tutorial from the main app logic

Here we are developing an email client software which has a specific UI that we need to teach that to the user.
There are some classes which handle the logic of the application. for example there is function like this in the one of main classes of project:
public void ComposeMessage(string username,string message)
{
MessageComposer.ComposeMessage(username, message);
}
so, in the above function we send a message to a user.
but in the another side of the application; there is a tutorial phase . so when user goes into tutorial side of the application , he can interact with application's buttons which we tell him , but we don't want to send real messages. so we have changed the function above like this:
public void ComposeMessage(string username,string message)
{
if(!Global.IsTutorial)
MessageComposer.ComposeMessage(username, message);
}
So there are many functions which we are adding if(!Global.IsTutorial) in their body. How can we avoid this situation? We don't want to change the body of the functions in the tutorial section and we don't want to add more codes and classes into our project. We want to keep changes low as much as possible.
There is a lot of ways to achieve what you want but all of them imply that, to start with, you don't use ComposeMessage directly but create interface for it and refactor callers to inject it as a dependency:
public interface IMessageComposer
{
void ComposeMessage(string username, string message);
}
public class MyApp
{
IMessageComposer messageComposer;
public MyApp(IMessageComposer messageComposer)
{
this.messageComposer = messageComposer;
}
public void Foo()
{
messageComposer.ComposeMessage(username, message);
}
}
When you don't rely on concrete implementation and inject dependencies you may change implementation of IMessageComposer to whatever you like without actually touching original MessageComposer's or MyApp's code.
For example you can create TutorialMessageComposer like this
public class TutorialMessageComposer : IMessageComposer
{
public void ComposeMessage(string username, string password)
{
Console.WriteLine("Tutorial mode!");
}
}
And RoutingMessageComposer decorator which will check current mode and call right composer
public class RoutingMessageComposer : IMessageComposer
{
IMessageComposer composer;
IMessageComposer tutorialComposer;
public RoutingMessageComposer(IMessageComposer composer, IMessageComposer tutorialComposer)
{
this.composer = composer;
this.tutorialComposer = tutorialComposer;
}
public void ComposeMessage(string username, string message)
{
if (Global.IsTutorial)
tutorialComposer.ComposeMessage(username, message);
else
composer.ComposeMessage(username, message);
}
}
After all preparations completed, you just need to stick RoutingMessageComposer into MyApp
var app = new MyApp(new RoutingMessageComposer(new MessageComposer(), new TutorialMessageComposer()));

C# - MS Test - Create a test that runs another test first

In our application, I have created a login test for our website. If this test is successful then login is successful. Now to create tests for other parts of the website, I need to perform login first.
Is there a way so that all the other tests that I will create will run the login test first? For example: is it possible to create a custom login test attribute that I can put on all other test methods, so that they will run login first? But then I also need the return value from that login test !
If not, then I will have to just write a plain C# function that performs login operation and I will need to put that function call, as the first line of every test.
When you're writing unit tests, you are testing each method in isolation. Meaning, the method that you're testing must not, and cannot depend on anything else in order to run.
The reason why you have a problem now, probably is because you broke at least the single responsability principle (the one that states that your class should only have one single reason to be changed). I can assume this because you are stating that your OTHER methods in a class depend on login being successful. Here's how to solve it:
Make an interface for your login method, something like:
public interface ILoginManager{
void Authenticate(string username, string password);
void IsAuthenticated{ get;}
}
Next, using the Dependency Inversion Principle, add this interface to your class with methods in it:
public class MyWorkerClass
{
private readonly ILoginManager _loginManager;
public MyWorkerClass(ILoginManager loginManager){
_loginManager = loginManager;
}
public bool LogOnUser(string userName, string password){
_loginManager.Authenticate(userName, password);
return _loginManager.IsAuthenticated;
}
}
Now, in all your tests, you can mock out the LoginManager, and set your expectations there, i.e.
[TestMethod]
public void SomeMethod_UserIsAuthenticated_InvokesSomeOtherMethod()
{
// Arrange
GetMockFor<ILoginManager>().SetupGet(lm => lm.Authenticated).Returns(true);
// Act
var result = Instance.SomeMethod();
// Assert
GetMockFor<ISomeOtherInterface>()
.Verify(o => o.SomeOtherMethod(), Times.AtLeastOnce() );
}
What about a base class?
[TestClass]
public class AuthenticatedTest
{
[TestInitialize]
public void TestInitialize()
{
// login
}
}
[TestClass]
public class MyTests : AuthenticatedTest
{
[TestMethod]
public void Whatever()
{
// already logged in.
}
}
You should not write tests which rely on other tests. If you need to log in before, you have to log n before, not "run the login test". It is probably not much difference of the code, but of the concept.

C# MVVM Handling and Passing UserID to different Models and ViewModels

My current implementation of passing UserID in my application is through the constructor.
i.e. SomeObject s = new SomeObject(userID)
Where in there is a code behind that does things based on the userID. The userID is further keep tracked by adding another property named "CurrentUser", however this seems to be a dirty solution as I have to implement it to all ViewModels and it seems to violate the "DRY" concept.
The second approach I have in mind is creating a public static variable on my MainWindowViewModel where all my other models can refer to it as MainWindowViewModel.CurrentUser.
Is one of the two approach the correct way to do this or is there a better approach that i don't know about?
You need to carefully analyze up front what you want to achieve with your application. Are you happy with there only ever being one selected client? Or will you need to have multiple clients being viewed or edited at a time (i.e. you have an MDI style app)?
Going with the single client approach is easy, you can implement the global property bag as already mentioned in other answers. But I will advise caution: if you build your app on the assumption there will only ever be one selected client it becomes a real PITA to try to refactor to make it multi-client capable. Using a centralized property bag or "session service" like this is indeed decoupling state from the VM, but the centralized service can still turn into a monstrosity over time and you build up too much dependence on it.
If you do want to go the multi-client route, then you are on the right track - but instead of passing a client identifier in on the constructor, pass (inject) the entire client data object. The chances are that you already have most of the client details available from the piece of UI that invokes the client oriented VM, so pass it in and save having to make another trip to your database to get the details.
Don't tie a current user to a ViewModel. I typically opt for a SessionService of some kind. If you're using Dependency Injection (DI), register a singleton of an ISessionService and concrete implementation. If your not using DI, then just have your app start create a singleton, like a SessionService.Current. Then you can put any items you need in here. Then each ViewModel can ask for the SessionService.Current.User and they have it. Your ViewModels shouldn't know about each other, but they can know about services. This keeps it DRY and loosely coupled, especially if you only access these session variables using the interface of an ISessionService and not the concrete implementation. This allows you to mock one up very easily without changing any ViewModel code.
What you have here is the problem of Communication between ViewModels. There are a number of solutions but my fave is the Mediator Pattern:
using System;
namespace UnitTestProject2
{
public class GetDataViewModel
{
IMediator mediator;
public GetDataViewModel(IMediator mediator)
{
this.mediator = mediator;
this.mediator.ListenFor("LoggedIn", LoggedIn);
}
protected string UserId;
protected void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
IMediator mediator;
public LoginViewModel(IMediator mediator)
{
this.mediator = mediator;
}
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
this.mediator.RaiseEvent("LoggedIn", this.UserId);
}
}
public interface IMediator
{
public void ListenFor(string eventName, EventHandler action );
public void RaiseEvent(string eventName, object data);
}
}
I Haven't implemented the Mediator here, because it can get quite involved and there are a number of packages available. but you can see the idea from my simple interface. Essentially the Mediator provides a Global list of EventHandlers which any Viewmodel can call or add to. You still have the problem of where to store the event names. Its nice to have these in enums, but that gives you a coupling problem. (a problem I usually ignore)
Alternatively you can have a Controller or (MasterViewModel if you love MVVM)
using System;
namespace UnitTestProject3
{
public class GetDataViewModel
{
protected string UserId;
public void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
public EventHandler OnLogin;
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
if (this.OnLogin != null)
{
this.OnLogin(this.UserId, null);
}
}
}
public class Controller // or MasterViewModel
{
public void SetUp()
{
GetDataViewModel vm1 = new GetDataViewModel();
LoginViewModel vm2 = new LoginViewModel();
vm2.OnLogin += vm1.LoggedIn;
//wire up to views and display
}
}
}

Async WCF: wait for another call

We have an old Silverlight UserControl + WCF component in our framework and we would like to increase the reusability of this feature. The component should work with basic functionality by default, but we would like to extend it based on the current project (without modifying the original, so more of this control can appear in the full system with different functionality).
So we made a plan, where everything looks great, except one thing. Here is a short summary:
Silverlight UserControl can be extended and manipulated via ContentPresenter at the UI and ViewModel inheritance, events and messaging in the client logic.
Back-end business logic can be manipulated with module loading.
This gonna be okay I think. For example you can disable/remove fields from the UI with overriden ViewModel properties, and at the back-end you can avoid some action with custom modules.
The interesting part is when you add new fields via the ContentPresenter. Ok, you add new properties to the inherited ViewModel, then you can bind to them. You have the additional data. When you save base data, you know it's succeeded, then you can start saving your additional data (additional data can be anything, in a different table at back-end for example). Fine, we extended our UserControl and the back-end logic and the original userControl still doesn't know anything about our extension.
But we lost transaction. For example we can save base data, but additional data saving throws an exception, we have the updated base data but nothing in the additional table. We really doesn't want this possibility, so I came up with this idea:
One WCF call should wait for the other at the back-end, and if both arrived, we can begin cross thread communication between them, and of course, we can handle the base and the additional data in the same transaction, and the base component still doesn't know anything about the other (it just provide a feature to do something with it, but it doesn't know who gonna do it).
I made a very simplified proof of concept solution, this is the output:
1 send begins
Press return to send the second piece
2 send begins
2 send completed, returned: 1
1 send completed, returned: 2
Service
namespace MyService
{
[ServiceContract]
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service1
{
protected bool _sameArrived;
protected Piece _same;
[OperationContract]
public Piece SendPiece(Piece piece)
{
_sameArrived = false;
Mediator.Instance.WaitFor(piece, sameArrived);
while (!_sameArrived)
{
Thread.Sleep(100);
}
return _same;
}
protected void sameArrived(Piece piece)
{
_same = piece;
_sameArrived = true;
}
}
}
Piece (entity)
namespace MyService
{
[DataContract]
public class Piece
{
[DataMember]
public long ID { get; set; }
[DataMember]
public string SameIdentifier { get; set; }
}
}
Mediator
namespace MyService
{
public sealed class Mediator
{
private static Mediator _instance;
private static object syncRoot = new Object();
private List<Tuple<Piece, Action<Piece>>> _waitsFor;
private Mediator()
{
_waitsFor = new List<Tuple<Piece, Action<Piece>>>();
}
public static Mediator Instance
{
get
{
if (_instance == null)
{
lock (syncRoot)
{
_instance = new Mediator();
}
}
return _instance;
}
}
public void WaitFor(Piece piece, Action<Piece> callback)
{
lock (_waitsFor)
{
var waiter = _waitsFor.Where(i => i.Item1.SameIdentifier == piece.SameIdentifier).FirstOrDefault();
if (waiter != null)
{
_waitsFor.Remove(waiter);
waiter.Item2(piece);
callback(waiter.Item1);
}
else
{
_waitsFor.Add(new Tuple<Piece, Action<Piece>>(piece, callback));
}
}
}
}
}
And the client side code
namespace MyClient
{
class Program
{
static void Main(string[] args)
{
Client c1 = new Client(new Piece()
{
ID = 1,
SameIdentifier = "customIdentifier"
});
Client c2 = new Client(new Piece()
{
ID = 2,
SameIdentifier = "customIdentifier"
});
c1.SendPiece();
Console.WriteLine("Press return to send the second piece");
Console.ReadLine();
c2.SendPiece();
Console.ReadLine();
}
}
class Client
{
protected Piece _piece;
protected Service1Client _service;
public Client(Piece piece)
{
_piece = piece;
_service = new Service1Client();
}
public void SendPiece()
{
Console.WriteLine("{0} send begins", _piece.ID);
_service.BeginSendPiece(_piece, new AsyncCallback(sendPieceCallback), null);
}
protected void sendPieceCallback(IAsyncResult result)
{
Piece returnedPiece = _service.EndSendPiece(result);
Console.WriteLine("{0} send completed, returned: {1}", _piece.ID, returnedPiece.ID);
}
}
}
So is it a good idea to wait for another WCF call (which may or may not be invoked, so in a real example it would be more complex), and process them together with cross threading communication? Or not and I should look for another solution?
Thanks in advance,
negra
If you want to extend your application without changing any existing code, you can use MEF that is Microsoft Extensibility Framework.
For using MEF with silverlight see: http://development-guides.silverbaylabs.org/Video/Silverlight-MEF
I would not wait for 2 WCF calls from Silverlight, for the following reasons:
You are making your code more complex and less maintainable
You are storing business knowledge, that two services should be called together, in the client
I would call a single service that aggreagated the two services.
It doesn't feel like a great idea to me, to be honest. I think it would be neater if you could package up both "partial" requests in a single "full" request, and wait for that. Unfortunately I don't know the best way of doing that within WCF. It's possible that there's a generalized mechanism for this, but I don't know about it. Basically you'd need some loosely typed service layer where you could represent a generalized request and a generalized response, routing the requests appropriately in the server. You could then represent a collection of requests and responses easily.
That's the approach I'd look at, personally - but I don't know how neatly it will turn out in WCF.

Categories