Hi Charlie, I'm afraid we're going to have some problems with this one. Here's what we want to accomplish:
Assert.That(async () => { return await Task.FromResult(1); }, Is.EqualTo(1)); The signature of our delegate is "delegate object ActualValueDelegate(void)" but the .NET async feature supports only methods returning void Task or Task<T>. In fact, if you try to compile the above you'll get: <snip> Cannot convert lambda expression to type 'object' because it is not a delegate type Cannot convert async lambda expression to delegate type 'NUnit.Framework.Constraints.ActualValueDelegate'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'NUnit.Framework.Constraints.ActualValueDelegate'. Since 'NUnit.Framework.TestDelegate' returns void, a return keyword must not be followed by an object expression </snip> The second paragraph in the compiler error is what we need to fix, the issue being that there is no delegate contravariance, which has been introduced in, IIRC, C# 3 for generic delegates. In other words, assigning an instance of a delegate returning Task<T> to a delegate type returning object is not allowed. So you would assume that introducing an overload for Assert.That as this one would fix it: public static void That(Func<object> method, ...) But it's not the case as you get this error now: <snip> Cannot convert async lambda expression to delegate type 'System.Func<object>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'System.Func<object>'. </snip> which is quite misleading to the point of being wrong. Look at the second sentence, it says that void, Task or Task<T> are not convertible to System.Func<object>, which is indeed the case but not really what we are doing here. It cannot infer the type of the lambda but complaining about incompatible return types which don't make any sense. In fact, keeping the above overload of Assert.That and changing the test code to this, it'll stop the compiler complaints: Assert.That(new Func<Task<int>>(async () => { return await ReturnOne(); }), Is.EqualTo(1)); But nonetheless this is not what we want our users to need to write. Therefore given the constraint of compiling for 2.0 which in turn prevents us from exposing types which were not in 2.0, like tasks, I think the only solution would be to add a generic overload, which won't require any special changes to the test code: public static void That<T>(Func<T> method, ...) How does this sound? -- You received this bug notification because you are a member of NUnit Developers, which is subscribed to NUnit V2. https://bugs.launchpad.net/bugs/1074568 Title: Assert/Assume should support an async method for the ActualValueDelegate Status in NUnit Test Framework: Triaged Status in NUnitLite Testing Framework: Triaged Status in NUnit V2 Test Framework: Triaged Bug description: Just as Assert.Throws can take an async method as it's argument, it should be possible to use an async method returning a value for Assert.That and Assume.That. To manage notifications about this bug go to: https://bugs.launchpad.net/nunit-3.0/+bug/1074568/+subscriptions _______________________________________________ Mailing list: https://launchpad.net/~nunit-core Post to : nunit-core@lists.launchpad.net Unsubscribe : https://launchpad.net/~nunit-core More help : https://help.launchpad.net/ListHelp