2015-07-21 43 views
0

我想模拟(使用Moq)类设置一个只显示两个属性的类的返回对象。设置一个只显示属性的Mocked(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 

} 

如果我使用precanned对象的建议我将如何“挂钩”,它与被测代码。例如,我写了一个单元测试,使用我的预先封装的对象而不是Moq,但是如何获得SUT使用的预先封装的对象?

+0

'CarResponse'是'PoCo'类,你为什么会想嘲弄吗? –

+0

@OldFox ...是的,它确实是一个PoCo ...我如何将它从单元测试“传递”给SUT? – GPGVM

+0

SUT的外观如何?这个例子中的问题是什么?(使用'CreateResponse'的例子)请添加UT,你正试图验证的场景和被测试的类... –

回答

1

很少有问题能在妥善单元的方式获得测试上面的代码:

  1. 新-ING了响应帮手
  2. 新-ING了CarResponseObject

实质上,除非真正的POCO中的类(即只有公开制定者和获得者的数据),使用“新”才是单元测试的杀手。即它不是单元测试(单独测试单元/方法)。它测试CarResponse ctor的行为,以及RequestHelper的工作。

考虑以下变化:

  1. 注入RequestHelper(所以你可以嘲笑CreateResponse法)
  2. 使用,并注入之类的一些映射工厂,这可以从汽车创造CarResponseObjects。
  3. 考虑CarResponse来实现类似IResponse的东西,所以你的RequestHelper或工厂可以返回接口。

与所有上述情况,您的测试看起来像(伪代码,不完整):

//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) 
+0

所以你明智地解释了我的很多焦虑。我正在使用一个具有20+以上圈复杂度的代码库。我试图在开始重构之前获得一个单元测试套件来提供一些覆盖范围。因此,现在它变得非常单调,“单元测试”不是孤立的,而是重构的目标。清理单元测试和代码库。 – GPGVM

0

您可以使用SetupGet和SetupSet来模拟属性。但是,我不认为你可以嘲笑具体的课程。

如果你正在处理一个值类型,你可能会发现它更容易不打扰嘲笑,并只使用预先封装的对象。

+0

从理论上讲,我明白你在说什么,但是在我的编辑中,你会发现我缺乏一些知识,无法按照你的建议去做。 – GPGVM