How to test race condition with async unit tests using NUnit? - c#

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

Related

How to await an async Command for unit testing?

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.

Force C# async tasks to be lazy?

I have a situation where I have an object tree created by a special factory. This is somewhat similar to a DI container, but not quite.
Creation of objects always happens via constructor, and the objects are immutable.
Some parts of the object tree may not be needed in a given execution and should be created lazily. So the constructor argument should be something that is just a factory for on-demand creation. This looks like a job for Lazy.
However, object creation may need to access slow resources and is thus always async. (The object factory's creation function returns a Task.) This means that the creation function for the Lazy would need to be async, and thus the injected type needs to be Lazy<Task<Foo>>.
But I'd rather not have the double wrapping. I wonder if it is possible to force a Task to be lazy, i.e. to create a Task that is guaranteed to not execute until it is awaited. As I understand it, a Task.Run or Task.Factory.StartNew may start executing at any time (e.g. if a thread from the pool is idle), even if nothing is waiting for it.
public class SomePart
{
// Factory should create OtherPart immediately, but SlowPart
// creation should not run until and unless someone actually
// awaits the task.
public SomePart(OtherPart eagerPart, Task<SlowPart> lazyPart)
{
EagerPart = eagerPart;
LazyPart = lazyPart;
}
public OtherPart EagerPart {get;}
public Task<SlowPart> LazyPart {get;}
}
I'm not sure exactly why you want to avoid using Lazy<Task<>>,, but if it's just for keeping the API easier to use, as this is a property, you could do it with a backing field:
public class SomePart
{
private readonly Lazy<Task<SlowPart>> _lazyPart;
public SomePart(OtherPart eagerPart, Func<Task<SlowPart>> lazyPartFactory)
{
_lazyPart = new Lazy<Task<SlowPart>>(lazyPartFactory);
EagerPart = eagerPart;
}
OtherPart EagerPart { get; }
Task<SlowPart> LazyPart => _lazyPart.Value;
}
That way, the usage is as if it were just a task, but the initialisation is lazy and will only incur the work if needed.
#Max' answer is good but I'd like to add the version which is built on top of Stephen Toub' article mentioned in comments:
public class SomePart: Lazy<Task<SlowPart>>
{
public SomePart(OtherPart eagerPart, Func<Task<SlowPart>> lazyPartFactory)
: base(() => Task.Run(lazyPartFactory))
{
EagerPart = eagerPart;
}
public OtherPart EagerPart { get; }
public TaskAwaiter<SlowPart> GetAwaiter() => Value.GetAwaiter();
}
SomePart's explicitly inherited from Lazy<Task<>> so it's clear that it's lazy and asyncronous.
Calling base constructor wraps lazyPartFactory to Task.Run to avoid long block if that factory needs some cpu-heavy work before real async part. If it's not your case, just change it to base(lazyPartFactory)
SlowPart is accessible through TaskAwaiter. So SomePart' public interface is:
var eagerValue = somePart.EagerPart;
var slowValue = await somePart;
Declaration:
private Lazy<Task<ServerResult>> _lazyServerResult;`
ctor()
{
_lazyServerResult = new Lazy<Task<ServerResult>>(async () => await
GetServerResultAsync())
}
Usage:
ServerResult result = await _lazyServerResult.Value;
Using the constructor for Task make the task lazy a.k.a not running until you say it to run, so you could do something like this:
public class TestLazyTask
{
private Task<int> lazyPart;
public TestLazyTask(Task<int> lazyPart)
{
this.lazyPart = lazyPart;
}
public Task<int> LazyPart
{
get
{
// You have to start it manually at some point, this is the naive way to do it
this.lazyPart.Start();
return this.lazyPart;
}
}
}
public static async void Test()
{
Trace.TraceInformation("Creating task");
var lazyTask = new Task<int>(() =>
{
Trace.TraceInformation("Task run");
return 0;
});
var taskWrapper = new TestLazyTask(lazyTask);
Trace.TraceInformation("Calling await on task");
await taskWrapper.LazyPart;
}
Result:
SandBox.exe Information: 0 : Creating task
SandBox.exe Information: 0 : Calling await on task
SandBox.exe Information: 0 : Task run
However I strongly recommend you to use Rx.NET and IObservable as in your case you will get way less troubles for handling less naive cases to start your task at the right moment.
Also it makes the code a bit cleaner in my opinion
public class TestLazyObservable
{
public TestLazyObservable(IObservable<int> lazyPart)
{
this.LazyPart = lazyPart;
}
public IObservable<int> LazyPart { get; }
}
public static async void TestObservable()
{
Trace.TraceInformation("Creating observable");
// From async to demonstrate the Task compatibility of observables
var lazyTask = Observable.FromAsync(() => Task.Run(() =>
{
Trace.TraceInformation("Observable run");
return 0;
}));
var taskWrapper = new TestLazyObservable(lazyTask);
Trace.TraceInformation("Calling await on observable");
await taskWrapper.LazyPart;
}
Result:
SandBox.exe Information: 0 : Creating observable
SandBox.exe Information: 0 : Calling await on observable
SandBox.exe Information: 0 : Observable run
To be more clear: The Observable here handle when to start the task, it is Lazy by default and will run the task everytime it is subscribed (here subscribe is used by the awaiter that enable the use of the await keyword).
You could, if you need to, make the task run only once every minute (or ever) and having its result published across all subscribers to save performance for instance, like in a real world app, all of this and many more is handled by observables.

How to use sequence when testing async methods?

I am using Moq.Sequences and I am having trouble with testing async methods.
When I do this:
[Test]
public async Task Demo()
{
using (Sequence.Create())
{
_fooMock.Setup(f => f.Fooxiate()).InSequence();
_barMock.Setup(b => b.Baronize()).InSequence();
var result = await _cut.DoMyStuffAsync();
Assert.AreEqual("someString", result);
}
}
The I get an exception in the production code when calling _foo.Fooxiate() saying:
Moq.Sequences.SequenceUsageException: 'Mock invocation can only be called with an active MockSequence created with MockSequence.Create()
Am I doing something wrong or is testing of call sequence in async methods not supported?
Here is the full demo code including the above mentioned production code:
using System.Threading.Tasks;
using Moq;
using Moq.Sequences;
using NUnit.Framework;
namespace TestingAsync.Tests
{
[TestFixture]
public class SomeClassTests
{
private SomeClass _cut;
private Mock<IFoo> _fooMock;
private Mock<IBar> _barMock;
[SetUp]
public void Setup()
{
_fooMock = new Mock<IFoo>();
_barMock = new Mock<IBar>();
_cut = new SomeClass(_fooMock.Object, _barMock.Object);
}
[Test]
public async Task Demo()
{
using (Sequence.Create())
{
_fooMock.Setup(f => f.Fooxiate()).InSequence();
_barMock.Setup(b => b.Baronize()).InSequence();
var result = await _cut.DoMyStuffAsync();
Assert.AreEqual("someString", result);
}
}
}
public class SomeClass
{
private readonly IFoo _foo;
private readonly IBar _bar;
public SomeClass(IFoo foo, IBar bar)
{
_bar = bar;
_foo = foo;
}
public async Task<string> DoMyStuffAsync()
{
return await Task.Run(() => DoMyStuff());
}
private string DoMyStuff()
{
_foo.Fooxiate();
_bar.Baronize();
return "someString";
}
}
public interface IBar
{
void Baronize();
}
public interface IFoo
{
void Fooxiate();
}
}
This other answer explains correctly how Moq.Sequences doesn't didn't properly support async / await due to its use of [ThreadStatic].
Based on the OP's request, I've updated that library to provide better support for modern concurrent programming patterns. (Hopefully, people are programming with Tasks these days, not Threads.)
Starting with version 2.1.0, you can make Moq.Sequences track the ambient sequence using a AsyncLocal<Sequence> instead of a [ThreadStatic] variable. This means that the ambient sequence can "flow" across async boundaries such as an await and still be visible in the continuation (which might run on a different thread).
For reasons of backwards compatibility, you currently need to opt in to the new behavior by doing the following before any of your tests run:
Sequence.ContextMode = SequenceContextMode.Async;
At this time of writing, the new behavior hasn't been extensively tested so issue and bug reports are welcome.
Moq.Sequences is not written to be multi-threaded as it uses the [ThreadStatic] attribute to keep track of the ambient Sequence.
[ThreadStatic]
private static Sequence instance;
The result is that the ambient Sequence is only stored for the current thread. Then you call Task.Run which spawns a background thread to do work. This results in the exception being thrown because instance is null for that thread.
if (Instance == null)
throw new SequenceUsageException(context + " can only be called with an active MockSequence created with MockSequence.Create()");
https://github.com/dwhelan/Moq-Sequences → src/Moq.Sequences/Sequence.cs
There is not a good way for Moq.Sequences to be able to guarantee order of calls in async code because:
Concurrent code does not typically have deterministic order of execution.
Async is an abstraction over threads and because of that is even less predictable than threads. There are many techniques that result in non-deterministic sequence of calls, such as doing work in background threads with Task.Run, using Parallel.For/ForEach, using TPL dataflow, using Task.WhenAll, etc.

execute aync methods in order

I have:
public myclass
{
public async Task method1();
public async Task method2();
public async Task method3();
}
I implement a function which should execute on myclass object these 3 mthods one after another. I am not sure which way is better (performance/correctness):
1)
public async Task mymethod(myclass obj)
{
await obj.method1();
await obj.method2();
await obj.method3();
}
myclass myobj = new myclass();
await myobj.method(myobj);
2)
public Task mymethod(myclass obj)
{
obj.method1();
obj.method2();
obj.method3();
}
myclass myobj = new myclass();
await myobj.method(myobj);
Only the first example is correct.
Even if you fixed the second example so that it returned a Task object, you still would have the problem that each individual method would be operating concurrently with the other two, which seems to be exactly what you don't want. I.e. in the second example, you don't wait for one method to finish before calling the next.
Since you would have to add some kind of waiting to the second example anyway, just to get it to work correctly, you should just go ahead and use the correct, idiomatic async/await technique seen in your first example.

TPL Fire and Forget using a Separate Class

I'm trying to implement fire and forget functionality, using the Task Parallel Library. With an inline call to Task.Factory.StartNew, everything works as expected. However, I want to move the Task.Factory.StartNew call into a separate class so that I can add logging, error handling, etc, and potentially upgrade the code in the future as better threading classes, etc are added to the .NET Framework, without duplicating code.
Below is a unit test that I would expect to pass, but that does not. I would appreciate help trying to figure out how to make this work.
[TestFixture]
public class ThreadingServiceFixture
{
public static bool methodFired = false;
[Test]
public void CanFireAndForgetWithThreadingService()
{
try
{
var service = new ThreadingService();
service.FireAndForget(() => methodFired = true);
var endTime = DateTime.Now.AddSeconds(1);
while(DateTime.Now < endTime)
{
//wait
}
Assert.IsTrue(methodFired == true);
}
finally
{
methodFired = false;
}
}
}
public class ThreadingService
{
public Task FireAndForget(Action action)
{
return Task.Factory.StartNew(() => action);
}
}
You're not executing the action, you're just returning it.
Try:
return Task.Factory.StartNew(() => action());
If is "fire and forget" you don't need to return the Task from the FireAndForget method, because the caller could get that Task and cancel it (strictly speaking the caller would "remember" of the call).
If you want to invoke this method from many services that do not inherit from a common ThreadingService you can implement an extension method via an interface.
public interface IFireAndForget
{
// no member needed.
}
public static class FireAndForgetExtensions
{
public static void FireAndForget(this IFireAndForget obj, Action action)
{
// pass the action, not a new lambda
Task.Factory.StartNew(action);
}
}
// using
public class ThreadingService : IFireAndForget
{
}
Also note the in your method you have to pass the action to the StartNew method insted of pass a lambda that return the action parameter.
You did not invoke the action in the ThreadingService
The code should read something like
public class ThreadingService
{
public Task FireAndForget(Action action)
{
return Task.Factory.StartNew(() => action.Invoke());
}
}
Additional note: testing state with a public field is evil. Think about repeatability, maintenance, running tests in different order. You should move bool methodFired inside the test. I would also assume there is a better technique to test this (but I am not sure which one).
Testing threaded code is hard.
Basing your tests on timing is a bad idea, they may become non-deterministic and you might observe erratic behavior on you build server. Imagine a tests that sometime passes and sometimes doesn't!
Your code has a bug, since you are not actually invoking the action.
But consider this variation:
[Test]
[TimeOut(5000)]
public void CanFireAndForgetWithThreadingService()
{
var service = new ThreadingService();
ManualResetEvent mre = new ManualRestEvent(bool); // I never remember what is the default...
service.FireAndForget(() => mre.Set() /*will release the test asynchroneously*/);
mre.WaitOne(); // blocks, will timeout if FireAndForget does not fire the action.
}
Yes, we are still using timing. But the test the timeout will happen only if the code breaks!
In all other scenarios, the test is absolutely predictable and takes a very short amount of time to execute, no waiting and praying for timing issues not to happen ;-)

Categories