99

I'm developing a Web API, and one of the test I came up with is that, if client makes a GET operation with a Physical Test ID (Physical Test is the resource I'm looking for) and that physical test is not found, the web API should return a 404 status.

Now, I'm using moq framework for my tests and I have the following code:

[TestMethod]
public void then_if_physical_test_not_found_return_not_found_status()
{
    var unitOfWork = new Mock<IUnitOfWork>();
    var repository = new Mock<IRepository<PhysicalTest>>();
    repository.Setup(r => r.FindById(It.IsAny<int>())).Returns();
    unitOfWork.Setup(m => m.PhysicalTests).Returns(repository.Object);
    var pt = new PhysicalTestResource(unitOfWork.Object);
    HttpResponseMessage<PhysicalTest> response = pt.GetPhysicalTest(43);
    Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode)
}

I need the Returns() method to return a null object, which is going to be what the actual API method would return if the resource is not found.

I tried sending null as a parameter in the Returns() method but had no success.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Daniel
  • 2,484
  • 4
  • 27
  • 35
  • To clarify, the error occurs because there are two overloads of `Returns`, one taking `T` (`T` = `IRepository` in this case) and one taking `Func`. When passing `null`, the compiler doesn't know which one to use, so you have to be specific. These overloads exist to give you the option to either return a static value `.Returns(new T())` or a new instance on every call `.Returns(() => new T())`. – JHBonarius Jul 20 '22 at 08:25

7 Answers7

286

You don't indicate what the error was, but this should work:

unitOfWork.Setup(m => m.PhysicalTests).Returns((IRepository<PhysicalTest>)null);

I suspect you tried to call it with Returns(null), which causes the compiler to complain since Returns is overloaded and it doesn't know which method should be called. Casting to a specific type removes the ambiguity.

Jeff Ogata
  • 56,645
  • 19
  • 114
  • 127
  • 10
    it worked, but I had to make this modification: unitOfWork.Setup(m => m.PhysicalTests).Returns((PhysicalTest)null); – Daniel Oct 27 '11 at 17:26
  • 1
    ah, ok... I assumed that since you were trying to return `repository.Object` that was the type returned by `PhysicalTests`. – Jeff Ogata Oct 27 '11 at 17:30
  • I tried the same thing and I'm getting a System.NotSupportedException. {"Invalid setup on a non-virtual (overridable in VB) member: x => x.GetFoo(.value.Id)"} Any ideas? – Dan Csharpster Jan 17 '17 at 18:07
  • @DanCsharpster You can only use Moq on interfaces or abstract classes with virtual members. Whatever class you're using that is the type of `x` is either a concrete class or an abstract class that has `GetFoo()` as non-virtual/overridable. – bcr Feb 22 '17 at 20:07
  • 1
    I can recommend this way of resolving the overload ambiguity. I just want to mention that, since the two non-generic overloads of `Returns` which are important here, have different names for their parameter, you can also resolve the ambiguity by writing: `... .Returns(value: null)` (here `value` is just the name of the parameter in the overload we want, it is not a keyword). – Jeppe Stig Nielsen Dec 11 '18 at 14:16
12

rt is a return type of method: FindById

repository.Setup(r => r.FindById(It.IsAny<int>())).Returns(Task.FromResult((rt)null));

Paradowski
  • 719
  • 1
  • 13
  • 17
Radhika Patwari
  • 131
  • 1
  • 6
10

If you are receiving an error like this:

enter image description here

You just need to specify the input parameter of 'Returns' method. Take a look in my example:

_ = _fileStorage.Setup(x => x.LoadDocument(It.IsAny<string>())).Returns(value: null);
Jorge Freitas
  • 790
  • 10
  • 18
5

Organization is a return type of method: Get

mockCache
    .Setup(cache => cache.Get(It.IsAny<string>(), It.IsAny<string>(),It.IsAny<string>()))
    .Returns(value: null as Organization);
WatersLake
  • 1,252
  • 2
  • 13
  • 21
1

Along with casting the member to null as mentioned by the accepted answer, this approach should work as well.

unitOfWork.Setup(m => m.PhysicalTests).Returns(() => null);
0

You could try this:

ref1.Setup(s => s.Method(It.IsAny<Ref2>(), It.IsAny<string>()))
     .Returns((Task<Ref3>)null);

ref1 = Mock Interface
Ref2 = Type request parameter
Ref3 = Type of return method mock
axtck
  • 3,707
  • 2
  • 10
  • 26
0

You're too close, you only need to pass the return type as generic type like so

repository.Setup(r => r.FindById(It.IsAny<int>())).Returns<IRepository<PhysicalTest>>(null);
Ali Jamal
  • 619
  • 7
  • 12