I am new to Unit Testing MVVM and using PRISM on my project. I am implementing Unit Testing on our current project and not having luck finding resources online that would tell me how totest DelegateCommand that calls async method. This is a follow up question to my post - How to Unit Test a ViewModel with async method. on how to unit test an async methods in MVVM and was answered that public methods can be tested using async TestMethod. This scenario will work only if the method that I want to test are public methods.
The problem is I want to test my DelegateCommand as this are the only public details that I want to expose on other classes and everything else are private. I can expose my private methods as public but I will never do this as its a bad design. I am not sure on how to go about this - Is DelegateCommand needs to be tested, or there are some other work around this? I am interested to know how other go about this and somehow lead me to the right path.
Here are my codes again
async void GetTasksAsync()
{
this.SimpleTasks.Clear();
Func<IList<ISimpleTask>> taskAction = () =>
{
var result = this.dataService.GetTasks();
if (token.IsCancellationRequested)
return null;
return result;
};
IsBusyTreeView = true;
Task<IList<ISimpleTask>> getTasksTask = Task<IList<ISimpleTask>>.Factory.StartNew(taskAction, token);
var l = await getTasksTask; // waits for getTasksTask
if (l != null)
{
foreach (ISimpleTask t in l)
{
this.SimpleTasks.Add(t); // adds to ViewModel.SimpleTask
}
}
}
also here is the command in my VM that calls the async method above
this.GetTasksCommand = new DelegateCommand(this.GetTasks);
void GetTasks()
{
GetTasksAsync();
}
and now my Test Method goes like
[TestMethod]
public void Command_Test_GetTasksCommand()
{
MyViewModel.GetTaskCommand.Execute(); // this should populate ViewModel.SimpleTask
Assert.IsTrue(MyBiewModel.SimpleTask != null)
}
Currently what I am getting is that my ViewModel.SimpleTask = null this is because it does not wait for the async method to finish.
Since I cannot add comments, for completeness sake, in PRISM 6 you could try:
I wrote an AsyncCommand class that returns a Task object from the
Execute
method. You then need to implementICommand.Execute
explicitly, awaiting the Task from yourExecute
implementation:You can then pass async Task-returning methods to the command class:
In your unit tests, you simply await the
Execute
method:The UI, on the other hand, will call the explicitly implemented
ICommand.Execute
method which takes care of awaiting the task.(*) In the meantime I noticed that if you follow common naming conventions, the Task-returning method should actually be named
ExecuteAsync
.In Prism 6, you can create
DelegateCommand
andDelegateCommand<T>
from async handler.For example:
startParsingCommand=DelegateCommand .FromAsyncHandler(StartParsingAsync,CanStartParsing) .ObservesProperty(()=> IsParserStarted);