I want to test the progress reporting of some async call which accepts a IProgress. I want to verify:
I want to use as few frameworks as possible -> a solution without using another 3. party library would be nice.
I tryed to write a simple async Task test methode to the achive this. I call the methode to test with await eg. await asyncCallToTest(new Progress((p) => { Assert.someting(p); }))
. And maybe use stack variables in the lambda. Full examples later.
This however resulted in Tests that succseed even if it should not be possible or sometimes a test passed and then it failed without changes....
I have recreated the issues with a simple stand alone test class:
using System;
using System.Threading.Tasks;
using NUnit.Framework;
namespace FastProgressReporter
{
public class Tests
{
[Test]
public async Task SampleOkTest()
{
await TestReporter(new Progress<double>((p) => {
Assert.GreaterOrEqual(p, 0);
Assert.LessOrEqual(p, 1);
}));
//Sometimes fails, sometims passes. Why?
}
[Test]
public async Task SampleFailTest()
{
await TestReporter(new Progress<double>((p) => {
Assert.GreaterOrEqual(p, 2); // Has to Fail, however passes.
Assert.LessOrEqual(p, 3);
}));
}
[Test]
public async Task ReportsIncremental()
{
double latestProgress = 0;
await TestReporter(new Progress<double>((p) => {
p = 1 - p; //Force Decrement...
Assert.GreaterOrEqual(latestProgress, p); //Should fail on second call
latestProgress = p;
}));
}
[Test]
public async Task ReportsOneOneOrMoreTimes()
{
double maxProgress = 0;
await TestReporter(new Progress<double>((p) => {
maxProgress = p > maxProgress ? p : maxProgress;
}));
Assert.AreEqual(0, maxProgress); //Should always fail
//Sometimes fails, sometims passes. Why?
}
// Methode under test
public static async Task TestReporter(IProgress<double> progress)
{
progress.Report(0);
await Task.Run(() => { /*Do nothing, however await*/ });
progress.Report(0.5);
await Task.Run(() => { /*Do nothing, however await*/ });
progress.Report(1);
}
}
}
VisualStudio 2019, .net-framework 4.7.2, NUnit3 test project
How do I achive my goals reliable and correctly?
Verifying progress reported from an async call is properly report in unit tests This uses a 3 party libary which I am trying to avoid and has the .Report() call inside of the test methode directly, not in the async mehoed called by the test
Thank you for your help.
As suggested by @Andrei15193, I tryed to implement IProgress by my self to get rid of the Progress class.
private class UnitTestProgress<T> : IProgress<T>
{
private Action<T> handler;
public UnitTestProgress(Action<T> handler)
{
this.hander = handler?? throw new ArgumentNullException(nameof(hander));
}
public void Report(T value)
{
handler(value);
}
}
I have chosen a very simple class here as an implmentation.
As far as I have tested, if Progress is replaced by my new class the problems are solved and the unittests are reliable.