2013-10-14 43 views
5

所以我正在爲我們的MVC4應用程序編寫測試,並且正在測試Controller的操作。正如我在標題中提到的那樣,測試仍然擊中服務(WCF)而不是返回測試數據。我有這樣的控制器:模擬對象仍在撥打服務

public class FormController : Controller 
{ 
    public SurveyServiceClient Service { get; set; } 
    public SurveyDao Dao { get; set; } 

    public FormController(SurveyServiceClient service = null, SurveyDao dao = null) 
    { 
     this.Service = service ?? new SurveyServiceClient(); 
     this.Dao = dao ?? new SurveyDao(Service); 
    } 

    // 
    // GET: /Form/ 

    public ActionResult Index() 
    { 
     var formsList = new List<FormDataTransformContainer>(); 
     Dao.GetForms().ForEach(form => formsList.Add(form.ToContainer())); 

     var model = new IndexViewModel(){forms = formsList}; 
     return View("Index", model); 
    } 

並使用這一DAO對象:

public class SurveyDao 
{ 
    private readonly SurveyServiceClient _service; 
    private readonly string _authKey; 

    public SurveyDao(SurveyServiceClient serviceClient) 
    { 
     _service = serviceClient; 
    } 

    .... 

    public FormContract[] GetForms() 
    { 
     var forms = _service.RetrieveAllForms(); 
     return forms; 
    } 

這是使用JustMock,在GetForms模擬()中的一個輔助類返回一些測試數據我的測試:

[TestClass] 
public class FormControllerTest 
{ 
    private SurveyDao mockDao; 
    private SurveyServiceClient mockClient; 

    public FormControllerTest() 
    { 
     mockClient = Mock.Create<SurveyServiceClient>(); 
     mockDao = Mock.Create<SurveyDao>(mockClient); 
    } 

    [TestMethod] 
    public void TestIndexAction() 
    { 
     //Arrange 
     var controller = new FormController(mockClient, mockDao); 
     Mock.Arrange(() => mockDao.GetForms()).Returns(TestHelpers.FormContractArrayHelper); 

     //Act 
     var result = controller.Index() as ViewResult; 

     //Assert 
     Assert.IsInstanceOfType(result.Model, typeof(IndexViewModel)); 
    } 
} 

我的問題是,當我運行測試時,服務仍然被調用。我已經使用Fiddler對此進行了驗證,並調試了測試並檢查了使用我們服務的測試數據填充的「result」的值。

編輯:

我已經改變了測試的構造是一個[TestInitialize]功能,所以測試現在看起來是這樣的:

[TestClass] 
public class FormControllerTest 
{ 
    private SurveyDao mockDao; 
    private SurveyServiceClient mockClient; 

    [TestInitialize] 
    public void Initialize() 
    { 
     mockClient = Mock.Create<SurveyServiceClient>(); 
     mockDao = Mock.Create<SurveyDao>(Behavior.Strict); 
    } 

    [TestMethod] 
    public void TestIndexAction() 
    { 
     //Arrange 
     var controller = new FormController(mockClient, mockDao); 
     Mock.Arrange(() => mockDao.GetForms()).Returns(TestHelpers.FormContractArrayHelper); 

     //Act 
     var result = controller.Index() as ViewResult; 

     //Assert 
     Assert.IsInstanceOfType(result.Model, typeof(IndexViewModel)); 
    } 
} 
+1

不應該GetForms是一個虛擬的方法? – rla4

+0

@ rla4,你爲什麼這麼說?嘲笑的方法需要虛擬嗎? – mam8cc

+1

這取決於。我對JustMock並不熟悉,但許多模擬框架都依賴於動態代理,這可能需要虛擬方法:) – rla4

回答

3

請確認您使用正確的JustMock程序集。有幾個不同的(VisualBasic,Silverlight,JustMock)。JustMock是你應該包括在你的項目中的一個。

未能包含正確的將導致您正在描述的行爲(方法未正確存根)。

1

JustMock manual解釋(由我亮點) :

默認情況下Telerik的JustMock使用寬鬆嘲笑,並允許您撥打 任何方法在給定的類型。 無論方法調用是否安排了 您都可以調用它。

呼喚你的Create()方法模擬時,您可以控制這種行爲:

var foo = Mock.Create<IFoo>(Behavior.Strict); 

在那裏,你可以指定mock對象應該怎麼做,如果你還沒有明確的實施一定的方法。在你的情況下(我認爲這是默認行爲),模擬確實調用了你想要模擬的對象的原始方法。

你必須在Behavior Enumeration列舉以下選擇:

  • 寬鬆:指定默認模擬電話會像一個存根,除非明確設置。
  • RecursiveLoose:指定默認情況下mock調用將返回模仿對象,除非明確設置。
  • 嚴格:指定在模擬上進行的任何調用如果未明確設置,將引發異常。
  • CallOriginal:指定默認情況下所有在mock上進行的調用都會調用其相應的原始成員,除非設置了一些預期。
+0

我修改了模擬,使其具有嚴格的行爲,並且服務仍被調用。 'mockDao = Mock.Create (Behavior.Strict);' – mam8cc

+1

@ mam8cc:嘗試添加一個['[[TestInitialize()]'](http://msdn.microsoft.com/zh-cn/library/microsoft .visualstudio.testtools.unittesting.testinitializeattribute.aspx)方法,並將'mockClient'和'mockDao'的實例移入其中,而不是使用'FormControllerTest()'構造函數。這有什麼區別嗎? –

+0

不可悲,它沒有。同樣的結果。作爲一些額外的信息,我已經通過調試驗證SurveyDao被設置爲模擬,只是爲了確保。 – mam8cc