0

I have a viewmodel class that is used as a base class for a ton of subclasses. I now added code to one of the base class's methods.

protected virtual void OnLanguageChanged(CultureInfo culture)
{
    CultureInfo.DefaultThreadCurrentCulture = culture;
    CultureInfo.DefaultThreadCurrentUICulture = culture;
}

This is to set the default culture on new threads.

I want to make sure that all derived classes, when they override this method, that they call "base.OnLanguageChanged". How can I write a unit test (I'm using Moq) that will fail when at least one derived class does not call this base method. The viewmodel has a property called ChildViewModelCollection which lists all child view models. The method that I'm overriding is called OnLanguageChanged(). Here is an idea of what I'm trying to do:

[TestMethod]
public void OnLanguageChangeCalledByDerivedClasses()
{
    var compositeViewModel = Container.Resolve<CompositeViewModel>();

    var children = compositeViewModel.ChildViewModelCollection;

    var newCulture = new CultureInfo("fr-CA");
    // Call method so that children run their overridden methods
    compositeViewModel.OnLanguageChanged(newCulture);

    // Now how do I check if base.OnLanguageChanged was called by all children
    foreach (var childViewModel in children)
    {

    }

    Assert.AreEqual(CultureInfo.DefaultThreadCurrentCulture, CultureInfo.DefaultThreadCurrentUICulture);
}
MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
Ray
  • 4,679
  • 10
  • 46
  • 92
  • OnLanguageChanged, is that an existing function in which you added those two lines , or is it a completely new function in the base class? – Ismail Hawayel Sep 04 '14 at 15:54
  • Yes, it's an existing function which had no code (open and closed parentheses). I added the two lines. – Ray Sep 04 '14 at 15:57
  • so the code does have child classes that are currently overriding this function? – Ismail Hawayel Sep 04 '14 at 15:59
  • @Ismail, yes, but I found some are not calling the base.OnLanguageChanged. And they now MUST call it. – Ray Sep 04 '14 at 16:01
  • 1
    It maybe a bit of work but I think the best thing to do is to force the behavior by changing the function to be overridden, check out:http://stackoverflow.com/questions/3982673/force-base-method-call – Ismail Hawayel Sep 04 '14 at 16:09
  • I think Ismail is right. Design it to prevent that, so you don't have to waste time on unit testing that. – Panu Oksala Sep 04 '14 at 16:52

1 Answers1

0

I agree with @Ismail, maybe a little refactoring in your design will be the best, but if you want just check if your subclasses are calling the base class method, I think you can use a code analysis tool like Nitriq (it's free), because what you want to do is more code analysis than unit test.

With the Nitriq rule below you can check if your classes that has OnLanguageChanged method are calling OnLanguageChanged inside the method:

var results = 
from method in Methods
where 
    method.Name.Equals("OnLanguageChanged")
&& !method.Calls.Any(c => c.Name.Equals("OnLanguageChanged"))
select new { method.MethodId, method.Name };
Warn(results, 0);
giacomelli
  • 7,287
  • 2
  • 27
  • 31