2014-09-25 36 views
0

我有一個從BaseController繼承的QuickController類。 QuickController中的一個方法調用對ConfigurationManager.AppSettings具有依賴性的BaseController上的屬性。測試依賴於基本屬性的方法

我想單元測試QuickController,但無法找到擺脫這種依賴關係的方法。下面是我的測試:

[TestMethod] 
public void TestMethod1() 
{ 
    var moqServiceWrapper = new Mock<IServiceWrapper>(); 

    var controller = new QuickController(moqServiceWrapper.Object); 

    //Act 
    var result = controller.Estimator(QuickEstimatorViewModel); 

    //Assert 
    Assert.IsInstanceOfType(result, typeof(ViewResult)); 
} 

的QuickController類

public class QuickController : BaseController 
{ 
    public QuickController(IServiceWrapper service) 
     : base(service) { } 

    public ActionResult Estimator(QuickEstimatorViewModel viewModel) 
    { 
     viewModel.RiskAddressLocation = RiskAddressLocation; 

     .... 

     return View("QuickQuote", viewModel); 
    } 
} 

而且BaseController財產

public RiskAddressLocation RiskAddressLocation 
{ 
    get { return ConfigurationManager.AppSettings["..."] 
          .ToEnum<RiskAddressLocation>(true); } 
} 

我還試圖呼籲,從QuickController繼承FakeQuickController的方法,但可以」不會覆蓋屬性,而是始終調用BaseController中的屬性。

我能在這裏做什麼嗎?

更新

從這裏接受的答案是什麼,我有這樣的VS2013不喜歡

public class BaseController{ 
    public virtual RiskAddressLocation RiskAddressLocation {get{...;} 
} 

public class QuickController : BaseController{} 

public class FakeQuickController : QuickController{ 
    public override RiskAddressLocation RiskAddressLocation 
    { 
     get { return ...} // Doesn't compile (cannot override because 
       //BaseController.RiskAddressLocation' is not a function 
    } 
} 

然而,這工作得很好

public class BaseController{ 
    public virtual RiskAddressLocation RiskAddressLocation(){...} 
} 

public class QuickController : BaseController{} 

public class FakeQuickController : QuickController{ 
    public override RiskAddressLocation RiskAddressLocation() 
    { 
     return ... ; 
    } 
} 
+1

好像你想[mock ConfigurationManager](http://stackoverflow.com/questions/9486087/how-to-mock-configurationmanager-appsettings-with-moq)而不是嘗試嘲笑基地? – CodingIntrigue 2014-09-25 12:14:25

+0

@RGraham夠了,但是如何攔截基類中的RiskAddressLocation以便能夠模擬它呢? – kooshka 2014-09-25 13:23:12

回答

1

您有一個非虛擬屬性取決於您想要模擬的具體方法。

基本上,你有三種選擇(因爲沒有上下文,我建議無論是後兩者的):

  • 使用隔離框架,例如像Microsoft Fakes
  • 修改BaseController並更改屬性爲虛擬
  • 刪除代碼的依賴(你應該擺在首位,如果你想跟着雄厚的設計做的),例如將它包裹在一個單獨的界面中
+0

如果我使RiskAddressLocation爲虛擬,那麼我只能從QuickController中覆蓋它。我無法重寫它,從一個從QuickController繼承的FakeQuickController中說。 – kooshka 2014-09-25 13:20:14

+1

這是不正確的 - 如果你讓一個成員變成虛擬的,你可以在任何派生類中覆蓋它,不管分離多少次。爲了給你最簡單的例子 - 你可以重寫任何類的ToString(即使是從另一個類繼承的類),即使原始方法在System.Object上定義。 – decPL 2014-09-25 13:23:40

+0

你是對的......和錯的;)你看,RiskAddressLocation是一個屬性,並且不允許我忽略來自大孩子的基礎。最後我得到了一些有意義的錯誤,它說這是不可能的,因爲它不是一個函數。所以我從一個屬性更改爲一個功能和...它的工作:)無論如何接受你的答案。謝謝。 – kooshka 2014-09-25 13:41:23

3

你可以寫一個適配器配置允許您在單元測試中提供存根配置。我確信有很多不同的實現,我喜歡Nathan Gloyn's IConfigurationManager implementation

然後,您將註冊WebConfigurationManagerAdapter作爲用於IConfigurationManager服務的組件,用於生產並使用Moq模擬單元測試中的接口。

另一件需要注意的事情是,如果你的ViewModel是一個簡單的DTO,我會在單元測試中傳遞一個真實的實例,因爲沒有優勢來嘲笑它。