Moq对象的Returns方法应该返回一个null对象。

100

我正在开发一个Web API,并且我想测试的其中一项是:如果客户端使用物理测试ID(物理测试是我要查找的资源)进行GET操作,但是找不到该物理测试,那么Web API应该返回404状态。

现在,我正在使用moq框架进行测试,以下是我的代码:

[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)
}

我需要Returns()方法返回一个空对象,这将是实际API方法在未找到资源时返回的内容。

我尝试将null作为参数发送到Returns()方法,但没有成功。


澄清一下,错误发生的原因是因为Returns有两个重载,一个接受T(在这种情况下,T=IRepository<PhysicalTest>),另一个接受Func<T>。当传递null时,编译器不知道该使用哪一个,因此您必须明确指定。这些重载存在的目的是为了让您选择返回静态值.Returns(new T())还是每次调用都返回新实例.Returns(() => new T()) - JHBonarius
7个回答

287

您没有指明错误是什么,但是这应该可行:

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

我猜你试图使用 Returns(null) 来调用它,这会导致编译器抱怨,因为 Returns 是重载的,而它不知道该调用哪个方法。将其强制转换为特定类型可以消除歧义。


10
它能正常运行,但我不得不进行以下修改: unitOfWork.Setup(m => m.PhysicalTests).Returns((PhysicalTest)null); - Daniel
1
啊,好的...我以为你试图返回repository.Object是因为它是PhysicalTests返回的类型。 - Jeff Ogata
我尝试了相同的事情,但是我得到了一个 System.NotSupportedException 错误。{"在非虚拟成员上进行无效设置(在 VB 中可以重写):x => x.GetFoo(.value.Id)"} 有什么想法吗? - Dan Csharpster
@DanCsharpster,你只能在接口或抽象类上使用Moq,并且这些接口或抽象类必须包含虚成员。无论你使用的类是x的类型,它都是一个具体类或者一个抽象类,其中GetFoo()不是虚拟/可重写的。 - bcr
1
我可以推荐这种解决重载歧义的方法。我只想提一下,由于在这里很重要的两个非泛型Returns重载具有不同名称的参数,您还可以通过编写... .Returns(value: null)来解决模棱两可的情况(这里value只是我们想要的重载中参数的名称,它不是关键字)。 - Jeppe Stig Nielsen

12

rt是一个方法的返回类型:FindById

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


10
如果你收到这样的错误信息:

enter image description here

你只需要指定'Returns'方法的输入参数即可。 看看我的例子:
_ = _fileStorage.Setup(x => x.LoadDocument(It.IsAny<string>())).Returns(value: null);

5

Organization是方法Get的返回类型。

mockCache
    .Setup(cache => cache.Get(It.IsAny<string>(), It.IsAny<string>(),It.IsAny<string>()))
    .Returns(value: null as Organization);

2

除了接受的答案中提到将成员转换为null之外,这种方法也应该可以起作用。

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

0

你太接近了,你只需要将返回类型作为泛型类型传递即可,像这样

repository.Setup(r => r.FindById(It.IsAny<int>())).Returns<IRepository<PhysicalTest>>(null);

0
你可以尝试这个:
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接