设置仅暴露属性的Mocked(Moq)类

时间:2015-07-21 15:25:29

标签: c# unit-testing moq

我试图模拟(使用Moq)一个类在一个只暴露两个属性的类上设置一个返回对象。

在我有限的Moq经验中,我通常会使用Setup()lamda来定义方法调用,然后使用Returns()来回吐所需的输出。

我在这里落下的是Setup()。没有"方法"在构造函数调用时调用,填充两个属性然后返回。

我想要嘲笑我的班级...显然是愚蠢的:

public class CarResponse
{
    public IMetaModel meta { get; set; }
    public List<ICarModel> cars { get; set; }

    public CarResponse(Common.Models.Car car)
    {
        this.cars = new List<ICarModel>();
    }
}

我嘲笑的微弱尝试:

private Mock<CarResponse> _carResponse = new Mock<CarResponse>(MockBehavior.Strict);
_carResponse.Setup( ????? ).Returns(new CarResponse() { meta = new MetaModelV2(), cars = foo });

进一步说明......这里是我试图编写单元测试的代码:

public HttpResponseMessage AddPickup()
{
     //....code removed for brevity....

    //this repository is mocked and returns the object exactly as I want it
     var car = carRepository.GetCar(carId);

   if (!errorInfo.Any()) //This check is bogus it never gets sets
   {
     RequestHelper rqh = new RequestHelper();

     response = rqh.CreateResponse(Request, HttpStatusCode.OK, new CarResponse(car));
}

我的单元测试:

[TestMethod]
public void AddValidPickupCorrectResponse()
{
   //arrange
   //...lots of code here left off for setting up http context etc

  //act---
  var response = controller.AddPickup();

  //assert

}

如果我按照建议使用预先安装的物体,我将如何勾选&#34;它到被测试的代码。例如,我编写了一个使用我的预装对象而不是Moq的单元测试但是如何让SUT使用该预装对象?

2 个答案:

答案 0 :(得分:1)

几乎没有什么问题可以妨碍对上述代码进行适当的单元测试:

  1. 新增响应助手
  2. 新建CarResponseObject
  3. 本质上,除非真正POCO中的一个类(即只有公共制定者和吸气者的数据),否则使用&#34; new&#34;是单元测试的杀手。即它不是单元测试(单独测试单元/方法)。它测试CarResponse ctor的行为,以及RequestHelper的工作。

    考虑以下变化:

    1. 注入RequestHelper(因此您可以模拟CreateResponse方法)
    2. 使用并注入一些sort的映射工厂,它可以从Car创建CarResponseObjects。
    3. 考虑使用CarResponse来实现类似IResponse的内容,因此您的RequestHelper或工厂可以返回接口。
    4. 综上所述,你的测试看起来像(伪代码,不完整):

      //arrange
      //....
      var carInDB = new Car();
      _repoMock.Setup(...).Returns(car);
      
      var carResponse = Mock.Of<IResponse>();
      _mapperMock.Setup(m=>m.CreateResponse(car).Returns(carResponse);
      
      var responseFromHelper = new WhateverResponseIsNeeded(); //(or create a new mock IResponse - note! new mock, different than car response
      _helperMock.Setup(_controller.Request, HttpStatusCode.OK, carResponse).Returns(responseFromHelper);
      
      //act
      var response = _controller.AddPickup();
      
      //assert
      response.Should().Be.SameInstanceAs(responseFromHelper)
      

答案 1 :(得分:0)

可以使用SetupGet和SetupSet到模拟性质。但是,我认为你不能嘲笑具体课程。

如果你正在处理一个值类型,你可能会发现更容易不打扰模拟,只是使用了一个预先设定的对象。