使用构建器模式单元测试和web api控制器

时间:2015-06-19 20:43:24

标签: c# unit-testing moq

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

首先,这是一个工作片段:

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????

我非常感谢任何我偏离轨道的指示。

1 个答案:

答案 0 :(得分:1)

此问题是由GetDat方法获取ref参数引起的。基本上,除非您将同一个实例传递给您传递给Setup的呼叫,否则它将无法与安装程序匹配。可以找到更多详细信息here,以及使用RhinoMocks的建议解决方法。我认为它可能也适用于NSubstitute,但我还没有测试过。

看看你正在做什么,你真的需要通过ref传递errorInfo吗?它是列表类的一个实例,可能是您的存储库可能添加的。是否真的需要将errorInfo重新分配给该类的其他实例?如果没有,那么您可以将签名更改为非参考签名,然后按如下方式设置您的模拟(要么应该工作):

_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());