0

I have a QuickController class that inherits from a BaseController. A method in QuickController calls a property on the BaseController which have a dependency on ConfigurationManager.AppSettings.

I want to unit test QuickController but can't find a way to get rid of that dependency. Here's my test:

[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));
}

The QuickController class

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

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

        ....

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

And the BaseController property

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

I also tried to call the method on a FakeQuickController that inherit from QuickController, but can't override the property, it's the one in the BaseController that is always called.

Is there anything I can do here?

Update

From the accepted answer here's what I had that VS2013 didn't like

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
    }
}

This however, works fine

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

public class QuickController : BaseController{}

public class FakeQuickController : QuickController{
    public override RiskAddressLocation RiskAddressLocation()
    { 
        return ... ;
    }
}
kooshka
  • 871
  • 1
  • 9
  • 19
  • 1
    Seems like you want to [mock ConfigurationManager](http://stackoverflow.com/questions/9486087/how-to-mock-configurationmanager-appsettings-with-moq) rather than attempt to mock the base? – CodingIntrigue Sep 25 '14 at 12:14
  • Fair enough @RGraham, but how do I intercept the RiskAddressLocation in the base class to be able to mock it? – kooshka Sep 25 '14 at 13:23

2 Answers2

3

You could write an adapter for Configuration to allow you to provide stub configuration in unit tests. I'm sure there are many different implementations for this; I like Nathan Gloyn's IConfigurationManager implementation.

Then you would register WebConfigurationManagerAdapter as the component to use for the IConfigurationManager service to use in production and use Moq to mock the interface in your unit tests.

One other thing to note, if your ViewModel is a simple DTO, I would pass a real instance in the unit test as there is no advantage to mocking it.

Russ Cam
  • 124,184
  • 33
  • 204
  • 266
1

You have a non-virtual property that depends on a concrete method that you want to mock.

Basically you have three options (given no context, I'd suggest either of the latter two):

  • Use an isolation framework, like e.g. Microsoft Fakes
  • modify your BaseController and change the property to virtual
  • remove the dependency in code (which you should do in the first place if you want to follow SOLID design), e.g. wrapping it in a separate interface
decPL
  • 5,384
  • 1
  • 26
  • 36
  • If I make RiskAddressLocation virtual I can only override it from QuickController. I can't override it, say from a FakeQuickController that inherits from QuickController. – kooshka Sep 25 '14 at 13:20
  • 1
    That's incorrect - if you make a member virtual, you can override it in any derived class, no matter how many times separated. To give you the simplest possible example - you can override `ToString` on any class (even one that inherits from a different class), even though the original method is defined on `System.Object`. – decPL Sep 25 '14 at 13:23
  • You are right... and wrong ;) You see, RiskAddressLocation is a property and that doesn't allow me to override base from the grand-child. Finally I got some meaningful error and it said it's not possible because is not a function. So I changed from a property to a function and... it works :) Accepting your answer anyway. Thanks. – kooshka Sep 25 '14 at 13:41
  • @kooshka I'm glad it works for you, but out of curiosity - could you share how you tried to do it? Because you **definitely can** override a property from a 'grand-child'; this code simply works: http://pastebin.com/fqc5Sf5Z – decPL Sep 25 '14 at 13:48