2015-07-21 46 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