2014-04-23 29 views
0

我正在編寫單元測試,我遇到的其中一個問題是不屬於DI的私有類或未在構造函數參數上初始化的空例外。任何人都可以幫助我?這是我的代碼。我的問題是,如何模擬PPortalSessionVariables類。在構造函數中未初始化調用私有類方法

控制器:

public class EducatorController : BaseController 
{ 
    //Note: PPortalSessionVariables class should NOT be part of IOC 
    private readonly IPPortalSessionVariables _ppsessionVariable = new PPortalSessionVariables(); 
    private readonly IEducatorService _educatorService; 

    public EducatorController(IEducatorService educatorService) 
    { 
     _educatorService = educatorService; 
    } 

    public ActionResult Index() 
    { 
     //during test null exception occurs on _ppsessionVariable.CurrentChild.Id 
     var model = _educatorService.GetEducatorsForChild(Convert.ToInt64(_ppsessionVariable.CurrentChild.Id)); 
     return View(model); 
    } 
} 

測試類:

[TestClass] 
public class EducatorControllerTests 
{ 
    public EducatorController CreateController(Mock<IEducatorService> educatorService = null) 
    { 
     educatorService = educatorService ?? new Mock<IEducatorService>(); 
     HttpContext.Current = HttpMockHelpers.FakeHttpContextCurrent(); 
     var controller = new EducatorController(educatorService.Object); 
     controller.SetFakeControllerContext("?site=2"); 
     return controller; 
    } 

    [TestMethod] 
    public void Index_Get_ReturnIndexView() 
    { 
     var ppsessionVariable = new Mock<IPPortalSessionVariables>(); 
     var controller = CreateController(); 
     var child = new ChildModel(); 
     child.Id = 0; 
     ppsessionVariable.Setup(x => x.CurrentChild).Returns(child); 
     var result = controller.Index() as ViewResult; 
     Assert.IsNotNull(result); 
    } 
} 

回答

1

不明白爲什麼你不使用它作爲任何其他依賴通過國際奧委會將其注入。至於Moq的工作,你應該嘲笑那個類,但永遠不能設置該對象,也許一個解決方法是爲該屬性創建一個setter,並調用傳遞模擬對象的測試中的屬性。

EducatorController

public void SetPortalSession(IPPortalSessionVariables portal) 
{ 
    _ppsessionVariable = portal; 
} 

EducatorControllerTests

[TestMethod] 
public void Index_Get_ReturnIndexView() 
{ 
    var ppsessionVariable = new Mock<IPPortalSessionVariables>(); 
    var controller = CreateController(); 
    controller.SetPortalSession(ppsessionVariable.object); 
    var child = new ChildModel(); 
    child.Id = 0; 
    ppsessionVariable.Setup(x => x.CurrentChild).Returns(child); 
    var result = controller.Index() as ViewResult; 
    Assert.IsNotNull(result); 
    } 
+0

謝謝你解決了我的問題。 –

2

有兩件事情是真的導致這種頭疼的你:

  1. 事實上,_ppSessionVariable是私有的,而不是暴露外界世界
  2. 有一個假設,即IPPortalSessionVariables.CurrentChild應該不會返回null,該接口

的所有實現如果你解決任何這些問題,那麼你的問題消失。

  1. 公開setter以允許單元測試明確地將_ppsessionVariable設置爲模擬對象。喜歡的東西:

    public void SetSessionVariable(IPPortalSessionVariables ppsessionVariable) 
    { 
        _ppsessionVariable = ppsessionVariable; 
    } 
    
  2. 重構代碼,以防止_ppsessionVariable.CurrentChild從返回null

    最簡單的事情可能是將CurrentChild初始化爲Null Object,在PPortalSessionVariables構造函數中。

2

您的EducatorControllerPPortalSessionVariables顯然非常緊密相連。直到控制器單元中有new PPortalSessionVariables()時,將無法進行單獨測試。 爲了解決這個問題,請確保EducatorController取決於抽象IPPortalSessionVariables而不是具體實現。

像其他人一樣已經建議,考慮有一個公開的二傳手IPPortalSessionVariables或繼續建設者注射。

相關問題