简体   繁体   中英

Overriding protected methods in Moq

I have a class which implements an abstract class. The abstract class has a protected virtual method as shown:

protected virtual void OnAction(string action, object result);

The class implementing the abstract class has a method which when completed calls base.OnAction .

I am trying to override the behaviour of the implementation of OnAction in my unit tests as I am trying to unit test only, not do integration tests.

My Moq call is setup as follows:

mock.Protected().Setup("OnAction", ItExpr.IsAny<string>, ItExpr.IsAny<object>());

Breakpointing my base abstract classes OnAction method confirms it is still being called.

I'm essentially wanting Moq to do the equivalent in it's emitted class:

public override OnAction(string action, object result) { // do nothing }

I'm not sure why you'd expect different, you're mocking a method that is never invoked in your concrete implementation.

What you have currently looks something like this:

public abstract class Derple
{
    protected virtual void OnAction(string action, object result) { Console.WriteLine("Derple"); }
}

public class Herple : Derple
{
    public void DoTheHerple(string action, object result) { base.OnAction(action, result); }
}

So by mocking the Herple OnAction method you're mocking something that's never invoked, since the concrete DoTheHerple call is still invoking the base class implementation.

An ugly way around this is to override the method in your child class, and invoke the base class method there, and then invoke this.OnAction in your child class method.

public abstract class Derple
{
    protected virtual void OnAction(string action, object result) { Console.WriteLine("Derple"); }
}

public class Herple : Derple
{
    protected override void OnAction(string action, object result) { base.OnAction(action, result); }
    public void DoTheHerple(string action, object result) { this.OnAction(action, result); }
}

This will make your test function as you're wanting, but it's arguably indicative of a flaw in your design that it's necessary.

*Edit

As Matthew pointed out, the override isn't actually necessary for this to work.

public class Herple : Derple
{
    public void DoTheHerple(string action, object result) { OnAction(action, result); }
}

works as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM