2014-09-25 39 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,我会在单元测试中传递一个真实的实例,因为没有优势来嘲笑它。