最小起订量对象设置范围/上下文因构建器模式单元测试和 Web api 控制器而丢失

MOQ object setup scope / context being lost with builder pattern unit test and web api controller

我正在为控制器编写单元测试并且 运行 遇到了一个问题,在我注入模拟对象时似乎没有设置它。但是,如果我在控制器端点创建模拟对象,一切正常。最后,为了使事情更加复杂,我正在通过流畅的构建器模式进行单元测试。

首先这是一个工作片段:

public HttpResponseMessage AddSlot(AddSlotRequest requestList)
{
   var errorInfo = new List<ErrorInfo>();

   Mock<IdatRepository> _xRepository = new Mock<IdatRepository>();

   _xRepository.Setup(x => x.GetDat(It.IsAny<Guid>(), ref errorInfo))
     .Returns(new Dat());

 ....snip....

 var crt = _xRepository.Object.GetDat(datId, ref errorInfo);
  //crt object returned as expected from mock

 ....snip

}

现在请注意,这会涉及更多内容。

首先,我的控制器由构建器创建:

public class AddSlotControllerBuilder
{
    //private backing field for fluent methods to act upon
    private Mock<IdatRepository> _xRepository = new Mock<IdatRepository>();

    //exposed property for external interactions...
    //not doing any yet but had plans so that is why it is here
    public Mock<IdatRepository> MoqdatRepository { get; private set; }

    //following the builder pattern the build method is called to return 
    //the object after configuration complete
    public AddSlotController Build()
    {

       var errorInfo = new List<ErrorInfo>();
       _xRepository.Setup(x => x.GetDat(It.IsAny<Guid>(), ref errorInfo)).Returns(new Dat());


        //assign private mock field to property
        MoqdatRepository = _xRepository;

        return new AddSlotController(_xRepository.Object);
    }
}

现在我的单元测试使用构建器:

[TestMethod]
public void AddValidPickupSlotCorrectResponse()
{
   var errorInfo = new List<ErrorInfo>(); //ref field 

   //arrange
   //1. controller
   AddSlotController controller = new AddSlotControllerBuilder().Build();

  //skipping APSR for brevity

   //act
   controller.AddPickupSlot(APSR);

}

终于在控制器中了

  var crt = _xRepository.Object.GetDat(datId, ref errorInfo);
  //crt is null????

任何我偏离轨道的指示都将不胜感激。

此问题是由您的 GetDat 方法采用 ref 参数引起的。本质上,除非您将相同的实例传递给您传递给 Setup 的调用,否则它将无法匹配设置。可以找到更多详细信息 here,以及使用 RhinoMocks 的建议解决方法。我认为它可能也适用于 NSubstitute,但我还没有测试过。

看看你在做什么,你真的需要 errorInfo 由 ref 传递吗?它是列表 class 的一个实例,您的存储库可能会添加到该列表中。真的需要将 errorInfo 重新分配给 class 的另一个实例吗?如果没有,那么您可以将签名更改为非参考签名,然后按如下方式设置您的模拟(两者都应该有效):

_xRepository.Setup(x => x.GetDat(It.IsAny<Guid>(), It.IsAny<List<ErrorInfo>>()))
                         .Returns(new Dat());

_xRepository.Setup(x => x.GetDat(It.IsAny<Guid>(), errorInfo))
                         .Returns(new Dat());