2013-08-24 36 views
0

當我試圖測試一個ASP.Net MVC控制器/動作時,我很難在單元測試模式中纏繞我的頭。如何在操作中對具有私有方法的ASP.Net MVC控制器進行單元測試?

用下面的代碼,我試圖寫的ShowPerson()方法測試:

public class PersonController : Controller 
{ 
    private IDataAccessBlock _dab; 

    public PersonController() 
     : this(new DataAccessBlock()) 
    { } 

    public PersonController(IDataAccessBlock dab) 
    { 
     _dab = dab; 
    } 

    public ActionResult ShowPerson(PersonRequestViewModel personRequest) 
    { 
     var person = GetPersonViewModel(personRequest); 
     return View("Person", person); 
    } 

    private PersonViewModel GetPersonViewModel(PersonRequestViewModel personRequest) 
    { 
     var personService = new CommonDomainService.PersonService(_dab); 
     var dt = personService.GetPersonInfo(personRequest.Id); 
     var person = new PersonViewModel(); 

     if (dt.Rows.Count == 1) 
     { 
      person.FirstName = dt.Rows[0]r["FIRSTNAME"]); 
      person.LastName = dt.Rows[0]["LASTNAME"]; 
     } 
     return person; 
    } 
} 

,我使用(使用NUnit和MOQ)測試:

[Test] 
public void ShowPerson_Action_Should_Return_Person_View() 
{ 
    // Arrange 
    string expected = "Person"; 
    Mock<PersonRequestViewModel> personRequestViewModelMock = new Mock<PersonRequestViewModel>(); 
    personRequestViewModelMock.SetupProperty(f => f.Id, 123456); 

    Mock<IDataAccessBlock> mockDab = new Mock<IDataAccessBlock>(); 
    PersonController personController = new PersonController(mockDab.Object); 

    // Act 
    ViewResult result = personController.ShowPerson(personRequestViewModelMock.Object) as ViewResult; 

    // Assert 
    personRequestViewModelMock.Verify(); 
    result.Should().Not.Be.Null(); 
    if (result != null) Assert.AreEqual(expected, result.ViewName, "Unexpected view name"); 
} 

一切似乎直到行if (dt.Rows.Count == 1)遇到。我得到一個「未設置爲對象實例的對象引用」。

我認爲一定有什麼時髦與方式,以下兩行寫:

var personService = new CommonDomainService.PersonService(_dab); 
var dt = personService.GetPersonInfo(personRequest.Id); 

,但我不知道在哪裏可以從這裏走。我有很多看起來像這樣的代碼。我做錯了什麼,或者有沒有真正的方法來測試?

感謝您的任何幫助或指針。

+0

掛鉤一個調試器,看看發生了什麼。 –

+0

@DanielMann我已經這樣做了。 'dt'爲空,因爲'GetPersonInfo()'方法正在使用模擬數據訪問塊。在下面的回答中,@sri指出了我的正確方向。我添加了一個簡短的問題,我希望他能夠清理,然後接受他的答案。 –

回答

1

是您的CommonDomainService.PersonService是某種web服務託管在您的web應用程序中,當您運行測試時,您的web應用程序將不會運行,服務將無法訪問。 理想情況下,您的控制器對您在私有方法中創建的CommonDomainService.PersonService具有依賴關係,而應該將其注入到Controller中(與您的DataAccess塊一樣),並在您的測試方法中對其進行模擬。

+0

感謝您的建議。我改變了私人PersonViewModel GetPersonViewModel(PersonRequestViewModel personRequest)'接受一個I​​CommonDomainService。在我的測試中,我添加了'mockCommonDomainService.Setup(x => x.GetPeronInfo(It.IsAny ()))。返回(new DataTable());'一切正常。但是,如果我新建一個DataTable(),爲它分配列並添加一行;然後在模擬設置的'.Returns()'中使用這個DataTable,當測試DataTable時它仍然是'null'。有什麼想法嗎? –

+0

我沒有看到新方法的任何問題,您能否發佈新代碼? –

+0

你說得對。一切正常。我在測試的早期版本中有一個錯誤。非常感謝。通過這個練習,我學到了很多東西。 –

0

write private readonly IDataAccessBlock _dab;而不是私人的IDataAccessBlock _dab;

+1

在這種情況下會有什麼幫助? –

相關問題