8

So I tried copying an example about exception throwing from the documentation, and added this to one of my methods:

.Returns( x => { throw new Exception(); });

But this results in the following compiler error:

Error CS0121 The call is ambiguous between the following methods or properties: 'SubstituteExtensions.Returns(T, Func, params Func[])' and 'SubstituteExtensions.Returns(Task, Func, params Func[])'

The method I'm using is an async method. I tried awaiting the method first, but that returns a different error, saying that it

can not return value of type X for (expected type Task`1)

UPDATE: I can change the lambda in the returns to be async as a way to get around the compiler error, but this results in a warning. So I guess the question now is more about whether or not there's a way to bypass this without having the warning show up, and without adding needless await code inside the lambda itself?

Is there a way to avoid this? I'm using NSubstitute 2.0.3

Thank you for any help.

Kolichikov
  • 2,944
  • 31
  • 46

2 Answers2

14

The compiler error in your question looks like you are calling something that returns Task rather than Task<T>? This sample works for me:

public interface ISample {
    Task DoStuff(string name);
}

[Test]
public async Task SampleTest()
{
    var sample = Substitute.For<ISample>();
    sample.DoStuff("test").Returns(x => { throw new Exception("doh"); });
    // ...
}

I tend to get that error when I have a generic Task<T>, which can be fixed by specifying the return type in the .Returns() call like this:

public interface IRepository {
    Task<int> FindId(string name);
}

[Test]
public async Task SampleTest2()
{
    var sample = Substitute.For<IRepository>();
    sample.FindId("test").Returns<int>(x => { throw new Exception("doh"); });
    // ...
}

In the example above I've removed the ambiguity by using .Returns<int>(...) which will pick the first overload mentioned in the compiler error.

If that does not help could you post the signature of the method being tested?

David Tchepak
  • 9,826
  • 2
  • 56
  • 68
  • Can you add the information to NSubstitute documentation? I've hit the same problem second time. Or consider some name changes to avoid ambiguity? – Michael Freidgeim Sep 24 '19 at 06:36
  • 1
    I fell over this issue too. I think updating the NSubstitute documentation to help people trying to throw errors when returning from `Task<>` would be a tremendous help. Something like the answer from @m12lrpv would be fabulous. – Zodman Mar 09 '21 at 08:39
5

Adding to Davids accepted answer if you want the Task method because your method does actually return a Task then you simply need to specify Returns<Task>.

object.Method().Returns<Task>(x => { throw new Exception("You messed up"); });

It's not necessary to specify the full return type i.e. don't do this -> Task<IEnumerable<YourClass>>

m12lrpv
  • 997
  • 2
  • 11
  • 18