I'm trying to unit test a command but because its an async command, the test method goes into the assertions before the command is finished. I have looked up solutions to this problem and they all talk about creating an AsyncCommand interface etc which I don't want to do as I only need to await the commands for the unit tests purposes. So is there another solution to this which is simpler and doesn't require creating another interface etc?
this is my Command class:
public class Command : ICommand
{
public void Execute(object parameter)
{
//exeute...
}
//other stuff....
}
Thats the tested class:
pubic class MyClass
{
private Command commandForTest;
public Command CommandForTest
{
get
{
if (commandForTest == null)
{
commandForTest = new Command(async (o) =>
{
if(someCondition)
await SomeMethod();
else
await AnotheMrthod();
});
}
return commandForTest;
}
}
}
This is the test Method:
[TestMethod]
public async Task Test()
{
MyClass myclass = new MyClass();
await Task.Run( () => myclass.CommandForTest.Execute());
//Assert....
}
So is there another solution to this which is simpler and doesn't require creating another interface etc?
No and yes. There is another solution. It is not simpler. The simplest and most straightforward solution is to use an IAsyncCommand interface. Or an AsyncCommand implementation that your unit test can cast the ICommand to (more brittle).
But if you want to go the hard way, then yes, you can technically detect when an async void method completes. You do this by writing your own SynchronizationContext and listening to OperationStarted and OperationCompleted. You'll also need to build a queue of work and write a main loop that processes the queue.
I have a type that does this. It is called AsyncContext and it is part of AsyncEx. Usage:
[TestMethod]
public void Test() // note: not async
{
MyClass myclass = new MyClass();
AsyncContext.Run(() =>
{
myclass.CommandForTest.Execute();
});
//Assert....
}
Again, I strongly recommend using IAsyncCommand. The real problem is that the core MVVM types are insufficient. So most people use IAsyncCommand or MvxAsyncCommand or AsyncCommand or expose the command logic as an async Task method on the VM.
Related
I want to unit test if an event raised by a dependency being subscribed by a class under test.
To set the context, I have the below interfaces and classes.
ITestedService.cs
public interface ITestedService
{
Task Start();
Task Stop();
}
IDependency.cs
public interface IDependency
{
event EventHandler<SoAndSoEventArgs> SomethingHappened;
Task Start();
Task Stop();
}
ISecondDependency
public interface ISecondDependency
{
Task DoYourJob(SoAndSo soAndSo);
}
TestedService.cs
public class TestedService : ITestedService
{
readonly IDependency m_dependency;
readonly ISecondDependency m_secondDependency;
public TestedService(
IDependency dependency,
ISecondDependency secondDependency)
{
m_dependency = dependency;
m_secondDependency = secondDependency;
}
public async Task Start()
{
m_dependency.SomethingHappened += OnSomethingHanppened;
await m_dependency.Start();
}
private async void OnSomethingHanppened(object sender, SoAndSoEventArgs args)
{
SoAndSo soAndSo = SoAndSoMapper.MapToDTO(args);
await m_secondDependency.DoYourJob(soAndSo),
}
}
With the above context, I want to Unit test Start() method of the TestedService class using xUnit.
I want to know how I can:
Assert if the event is attached to a handler.
Simulate the event IDependency.SomethingHappened being fired.
Verify if the OnSomethingHappened method is executed
Verify if the ISecondDependency.DoYourJob(soAndSo) is called.
From this answer, this documentation and from the guidance by #ZevSpitz in comments I was able to write the below tests for Start().
Though I couldn't verify if the same code path OnSomethingHappened got executed or was it some other subscription which calls m_secondDependencyMock.DoYourJob(soAndSo).
TestedServiceTest.cs
public class TestedServiceTest
{
readonly Mock<IDependency> m_dependencyMock;
readonly Mock<ISecondDependency> m_secondDependencyMock;
ITestedService testedService;
public TestedServiceTest()
{
m_dependencyMock = new Mock<IDependency>();
m_secondDependencyMock = new Mock<ISecondDependency>();
testedService = new TestedService(m_dependencyMock.Object, m_secondDependencyMock.Object);
}
[Fact]
public async Start_DependencyStartInvoked()
{
// Arrange
m_dependencyMock.Setup(x=> x.Start()).Verifyable();
// Act
await testedService.Start();
// Assert
//This tests if the IDependecy.Start is invoked once.
m_dependencyMock.Verify(x=>x.Start(), Times.Once);
}
[Fact]
public async Start_EventListenerAttached()
{
// Arrange
m_dependencyMock.Setup(x=> x.Start()).Verifyable();
m_dependencyMock.SetupAdd(m => m.SomethingHappened += (sender, args) => { });
// Act
await testedService.Start();
// Assert
// The below together with SetupAdd above asserts if the TestedService.Start adds a new eventlistener
// for IDependency.SomethingHappened
m_dependencyMock.VerifyAdd(
m => m.SomethingHappened += It.IsAny<EventHandler<SoAndSoEventArgs>>(),
Times.Exactly(1));
}
[Fact]
public async Start_SomthingHappenedInvoked_HandlerExecuted()
{
// Arrange
m_dependencyMock.Setup(x=> x.Start()).Verifyable();
m_secondDependencyMock.Setup(x=> x.DoYourJob(It.IsAny<SoAndSo>())).Verifyable();
// Act
await testedService.Start();
// This will fire the event SomethingHappened from m_dependencyMock.
m_dependencyMock.Raise(m => m.SomethingHappened += null, new SoAndSoEventArgs());
// Assert
// Assertion to check if the handler does its job.
m_secondDependencyMock.Verify(x=> x.DoYourJob(It.IsAny<SoAndSo>()), Times.Once);
}
}
The purpose of unit testing can be:
Verify logic results in the output you want
Verify crucial calls are made (I would only do if I want to make sure another developer does not remove a piece of code by mistake but in general verifying
whether some call is made is not necessary and even worse, makes
unnecessary maintainability work)
Having said that, you do not need to test the internals of the language. For example in this case you do not need to verify that when you register an event, that the method registered will be called. It is the job of the language to do that. That is tested by the language.
So you verified that the Start method does the calls that you expected. This by the way, as I mentioned above, only makes sense to do if there is a reason to do so such as purpose number 2 above.
Now you know the OnSomethingHappened is going to be triggered. The language guarantees that.
What you want to test is the actual implementation within OnSomethingHappened. For this, you need to make this method more testable by making it reachable (access modifier private is not going to work) and by making it's dependencies also mockable (SoAndSoMapper is not mockable).
Note: Unit testing is more of an activity of making code testable rather than the activity of figuring out how to write the test. If writing the test is difficult, that can be a sign that code is not easily testable.
public class TestedService
{
readonly IDependency m_dependency;
readonly ISomethingDoer m_somethingDoer;
public TestedService(
IDependency dependency,
ISomethingDoer somethingDoer)
{
m_dependency = dependency;
m_somethingDoer = somethingDoer;
}
public async Task Start()
{
m_dependency.SomethingHappened += m_somethingDoer.OnSomethingHanppened;
await m_dependency.Start();
}
}
interface ISomethingDoer
{
Task OnSomethingHanppened(object sender, SoAndSoEventArgs args);
}
class SomethingDoer : ISomethingDoer
{
readonly ISecondDependency m_secondDependency;
readonly ISoAndSoMapper m_soAndSoMapper;
public SomethingDoer(ISecondDependency secondDependency, ISoAndSoMapper soAndSoMapper)
{
m_secondDependency = secondDependency;
m_soAndSoMapper = soAndSoMapper;
}
public async Task OnSomethingHanppened(object sender, SoAndSoEventArgs args)
{
SoAndSo soAndSo = m_soAndSoMapper.MapToDTO(args);
await m_secondDependency.DoYourJob(soAndSo),
}
}
Now you can test what OnSomethingHappened does by creating a test class for SomethingDoer, mocking it's dependencies and verifying for example that given soAndSoMapper mock returns some value, the secondDependency is called with that value. Although once again, OnSomethingHappened doesn't do much. Therefore it is arguable whether you want to test this.
This question already has an answer here:
MVVM light Dispatcher unit tests
(1 answer)
Closed 2 years ago.
We have an application written in WPF.
I'm trying to write a unit test for some code that runs on background threads. On a few place in this code we need to do things on the UI thread. In those places we use the following code structure:
Application.Current.Dispatcher.Invoke(new Action(() =>
{
// do something on UI thread
}));
When I create an async unit test it seems to get stuck on the Invoke method. I guess this is because the dispatcher is not "dispatching". I've tried to fix this by using a class called DisaptcherUtil that is referenced in a number of places on the internet. But I can't get this to work. A simplistic version of my code now looks like this:
[TestMethod]
public async Task TestDispatcher()
{
new Application();
DispatcherUtil.DoEvents();
await Task.Run(() => MethodUsingDispatcher());
}
private void MethodUsingDispatcher()
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
Console.WriteLine("On the dispatchee thread!");
}));
Console.WriteLine("BAck to background trhead");
}
public static class DispatcherUtil
{
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
private static object ExitFrame(object frame)
{
Console.WriteLine("ExitFrame");
((DispatcherFrame)frame).Continue = false;
return null;
}
}
When I run the test called "TestDispatcher" it just hangs.
Anyone have any ideas why this is happening? Is this the right way to do this or should I instead go down the route of creating an interface for the Dispatcher that I could mock in the tests. I've seen this done in some places.
I'd say that you should hide the dispatching behind an interface and mock it in the unit tests:
interface IDispatcher
{
void Dispatch(Action action);
}
You can easily mock this in your tests and expect to those dispatched calls.
An implementation which uses the real dispatcher and can be used by your app:
public class Dispatcher : IDispatcher
{
public void Dispatch(Action action)
{
Application.Current.Dispatcher.Invoke(action);
}
}
This is the code I'm trying to test for a racing condition,
I have a legacy code which I can change to a certain extent.
Inside my main function, I have a function which returns a Task that we await and another function for UI that must not be blocked because it runs on a different thread.
In the original code we do not care about the result we are just initializing some classes, and I test that the ViewModel is not null.
In the example code I gave here, I changed the code to exemplify the problem of the race condition.
Currently, my test will fail. How do I properly test my racing condition?
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Myclass tempClass = new Myclass();
tempClass.CreateImage();
Assert.AreEqual(3, tempClass.Sum);
}
}
public class Myclass
{
public int Sum;
public Myclass()
{
Sum = 0;
}
public async Task CreateImage()
{
await InternalFunction();
await Task.Run(() => Physics());
}
public async Task InternalFunction()
{
await Task.Run(() =>
{
Math();
});
}
public void Math()
{
Sum += 1;
}
public void Physics()
{
Sum += 2;
}
}
If I run the test, the sum property will be 1, and not 3 as expected. How do I change the code to be able to perform all of the flow of CreateImage() function and only once all of the threads are done, I want to assert the result/content of TempClass.
You will have to await the code in the test itself as well, otherwise the Aseert will take place before the code has completed:
[TestMethod]
public async Task TestMethod1()
{
Myclass tempClass = new Myclass();
await tempClass.CreateImage();
Assert.AreEqual(3, tempClass.Sum);
}
But to me this code has some pifalls. There is a lot of wrapping synchronous code in Task.Run which won't give any benefits as it is right now. Also Sum is not threadsafe so if at any point in time it will be accessed by threads concurrent bad things can happen.
The CreateImage method is async, however your unit test method isn't, so your test may complete before CreateImage is finished.
You didn't specify which version of NUnit you're using, but the following works in the latest version of NUnit 3
[TestFixture]
public class UnitTest1
{
[Test]
public async Task TestMethod1()
{
Myclass tempClass = new Myclass();
await tempClass.CreateImage();
Assert.AreEqual(3, tempClass.Sum);
}
}
Of course, This assumes that MyClass is thread-safe - If your real code uses multiple threads concurrently modifying the state of a MyClass instance, then you may also need to consider using a synchronisation mechanism such as one of those built into the BCL - https://learn.microsoft.com/en-us/dotnet/standard/threading/synchronizing-data-for-multithreading
Also, you might consider using some of the async-friendly helpers developed by Stephen Cleary - https://github.com/StephenCleary/AsyncEx
I need to invoke a method that meets the following criteria.
The method may run for hours.
The method may interface with hardware.
The method may request user input (parameter values, confirmation, etc). The request should block the method until input has been received.
I have a prototype implementation that fulfills this criteria using the following design.
Assume a Form exists and contains a Panel.
The IntegerInput class is a UserControl with a TextBox and a Button.
public partial class IntegerInput : UserControl
{
public TaskCompletionSource<int> InputVal = new TaskCompletionSource<int>(0);
public IntegerInput()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int val = 0;
Int32.TryParse(textBox1.Text, out val);
InputVal.SetResult(val);
}
}
The Form1UserInput class is instanced by Form1. The container is a Panel set by Form1 before being provided to the invoking class.
public interface IUserInput
{
Task<int> GetInteger();
}
public class Form1UserInput : IUserInput
{
public Control container;
private IntegerInput integerInput = new IntegerInput();
public IntegerInput IntegerInput { get { return integerInput; } }
public async Task<int> GetInteger()
{
container.Invoke(new Action(() =>
{
container.Controls.Clear();
container.Controls.Add(integerInput);
}));
await integerInput.InputVal.Task;
return integerInput.InputVal.Task.Result;
}
}
The Demo class contains the method I want to invoke.
public class Demo
{
public IUserInput ui;
public async void MethodToInvoke()
{
// Interface with hardware...
// Block waiting on input
int val = await ui.GetInteger();
// Interface with hardware some more...
}
public async void AnotherMethodToInvoke()
{
// Interface with hardware...
// Block waiting on multiple input
int val1 = await ui.getInteger();
int val2 = await ui.getInteger();
// Interface with hardware...
}
}
This is a rough outline of what the invoking class looks like. The call to Task.Run() is accurate for my prototype.
public class Invoker
{
public async Task RunTestAsync(IUserInput ui)
{
object DemoInstance = Activator.CreateInstance(typeof(Demo));
MethodInfo method = typeof(Demo).GetMethod("MethodToInvoke");
object[] args = null;
((IUserInput)DemoInstance).ui = ui;
var t = await Task.Run(() => method.Invoke(DemoInstance, args));
// Report completion information back to Form1
}
}
The Form1 controller class instances the Invoker and calls RunTestAsync passing in an instance of Form1UserInput.
I am aware of some concerns about long running Tasks that may block and what that would mean for ThreadPool resources. However, the ability to invoke multiple methods at once is not provided by the application I am building. It's possible that the application may provide some other limited functionality while the invoked method is running but the current requirements do not specify such functionality in detail. I anticipate that there would only be one long running thread in service at any time.
Is the use of Task.Run() for this type of method invocation a reasonable implementation? If not, what would a more reasonable implementation be that provides for the required criteria? Should I consider a dedicated thread outside of the ThreadPool for this invocation?
Is the use of Task.Run() for this type of method invocation a reasonable implementation?
Assuming that your "interface with hardware" can only be done using synchronous APIs, then yes, Task.Run is fine for that.
However, I would change when it's called. Right now, Task.Run is wrapping an async void method that executes on the thread pool (and uses Invoke to jump back on the UI thread). These are each problematic: Task.Run over async void will seem to complete "early" (i.e., at the first await); and using Invoke indicates that there's some tight coupling going on (UI calls background service which calls UI).
I would replace the async void with async Task and also change where Task.Run is used to avoid Invoke:
public async Task<int> GetInteger()
{
container.Controls.Clear();
container.Controls.Add(integerInput);
// Note: not `Result`, which will wrap exceptions.
return await integerInput.InputVal.Task;
}
public async Task MethodToInvokeAsync()
{
await Task.Run(...); // Interface with hardware...
// Block waiting on input
int val = await ui.GetInteger();
await Task.Run(...); // Interface with hardware some more...
}
var t = await (Task)method.Invoke(DemoInstance, args);
I'd like to hear opinions on the best way to handle asynchronous operations with the Command pattern. Say we have the following example:
public class MyCommand
{
// Sets up receiver and does whatever stuff
public void Execute()
{
_myReceiver.DoSomething();
}
}
The problem is: MyCommand doesn't know whether MyReceiver.DoSomething() has async portions of code. If i wanted to push MyCommand into an undo stack after its execution, i couldn't guarantee that its receiver action has been fully executed, making it uncertain to know if MyCommand reached a state where undoing is possible or not.
I personally thought on the following solution:
Implement some sort of state control in Command
Include "BeginExecute" and "EndExecute" in Command
Include events in MyReceiver and make Command subscribe to them (that seems smelly to me)
To wrap things up, MyCommand would turn into:
public class MyCommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
_myReceiver.DoSomethingFinished += () => this.EndExecute();
}
public void BeginExecute()
{
this.EnterExecutionState();
_myReceiver.DoSomething();
}
public void EndExecute()
{
this.LeaveExecutionState();
}
// State handling related stuff
}
I now have the means to make sure the Command's receiver has finished executing whatever action and it's ready to be pushed into the undo stack. However, to event-spam every single Receiver class that contains async operations really bugs me.
I haven't found much about this topic in the Internet and would love to hear different approaches.
OBS: Make the Command manage all the asynchronous-related code isn't an option :).
I think you've got way too much going on in a single class. I would break it down like this:
// An immutable command, to be handled in-process.
// ICommand is a marker interface with no members.
public class DoSomething : ICommand
{
public readonly Id;
public DoSomething(Guid id)
{
Id = id;
}
}
// To be handled out-of-process.
[AsynchronousCommand]
public class DoSomethingThatTakesAReallyLongTime : ICommand
{
public readonly Id;
public DoSomethingThatTakesAReallyLongTime(Guid id)
{
Id = id;
}
}
// This guy could take any number of dependencies: ISomethingRepository, DbContext, etc.
// Doesn't matter, but it's probably gonna have dependencies.
public class DoSomethingHandler : IHandler<DoSomething>
{
public void Handle(DoSomething command) // IHandler<T>'s only member
{
// CRUD or call call a domain method
}
}
public class CommandService : ICommandService
{
public void Execute(params ICommand[] commands) // ICommandService's only member
{
foreach(var command in commands)
{
var handler = GetHandler(command); // Could use your IOC container.
if (HasAsyncAttribute())
new Action(() => handler.Handle(command)).BeginInvoke(null, null);
else
handler.Handle(command);
}
}
}
// Something that might consume these
public class SomethingController
{
private readonly ICommandService _commandService;
public SomethingController(ICommandService commandService)
{
_commandService = commandService;
}
[HttpPost]
public void DoSomething(Guid id)
{
_commandService.Execute(new DoSomething(id));
}
[HttpPost]
public void DoSomethingThatTakesAReallyLongTime(Guid id)
{
_commandService.Execute(new DoSomethingThatTakesAReallyLongTime(id));
}
}
The big advantage here is that you can distribute your commands to clients without explicitly dragging along all the dependencies that go with the handlers. The handlers should not be known to the client. All the client needs to know is that it sent a command, and all commands should be assumed to succeed.
Something like this?
public interface ICommand
{
void Execute();
event EventHandler Finished;
}
public class MyCommand : ICommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
_myReceiver.DoSomethingFinished += () => Finished(); // dont forget null check here.
}
public void Execute()
{
_myReceiver.DoSomething();
}
public event EventHandler Finished;
}
This way, user of this command can register to Finished event so it knows when command has finished its async behaviour and can act acordingly.
Or if you dont wan't to use event, then what about callback?
public class MyCommand : ICommand
{
public MyCommand(MyReceiver receiver)
{
_myReceiver = receiver;
}
public void Execute()
{
_myReceiver.DoSomething(() => Finished()); // dont forget null check here.
}
public event EventHandler Finished;
}
Either way, there simply need to be a way for MyReciever to notify its caller, that it finished. There is no way to bypass it.
First I would add to the name of the method Async to esplicitly signal to your Command class consumer that method executes in async way.
Second, I would add like parameter an Action<T> which will be called as method async call completes. So this method caller can be notified when async sction was terminated.
Edit
obj.DoSomethingAsync(... params, Action<T> onComplete)
If you are going to impose the requirement that all processing is completed before control returns to your Execute method, without modifying the calling code's behavior, you could modify the way that your actions execute.
First initialize all your asynchronous calls and block(wait) on the current thread for calls to return. I'm not sure what the nature of your asynchronous calls are, as in if they are in a Thread that you are aware of, or will be returned on an arbitrary thread, but you should be able to come up with some kind of thread synchronization for your problem.
Try using a Semaphore to block current thread(after calling your async methods), and release the semaphore when all your async methods have returned their response(s). This will have the effect of "re-synchronizing" your async calls.
You can use another synchronization method, but a Semaphore is simple enough to understand.