Lance Fisher
Lance Fisher

Reputation: 25813

Verifying protected abstract methods are called using Moq

Suppose I have the following class:

public class TestBase
{
  public bool runMethod1 { get; set; }

  public void BaseMethod() 
  {
    if (runMethod1)
      ChildMethod1();
    else 
      ChildMethod2();
  }

  protected abstract void ChildMethod1();
  protected abstract void ChildMethod2();
}

I also have the class

public class ChildTest : TestBase
{
  protected override void ChildMethod1()
  {
    //do something
  } 

  protected override void ChildMethod2()
  {
    //do something completely different
  }

}

I'm using Moq, and I'd like to write a test that verifies ChildMethod1() is being called when I call BaseMethod() and runMethod1 is true. Is it possible to create an implemention of TestBase with Moq, call BaseMethod() and verify that ChildMethod was called on the Moq implementation?

[Test]
public BaseMethod_should_call_correct_child_method()
{
  TestBase testBase;

  //todo: get a mock of TestBase into testBase variable

  testBase.runMethod1 = true;

  testBase.BaseMethod();

  //todo: verify that ChildMethod1() was called

}

Upvotes: 3

Views: 6257

Answers (4)

kzu
kzu

Reputation: 1871

You can also set the expectation/setup as Verifiable and do without a strict mock:

  //expect that ChildMethod1() will be called once. (it's protected)
  testBaseMock.Protected().Expect("ChildMethod1")
    .AtMostOnce()
    .Verifiable();

  ...

  //make sure the method was called
  testBase.Verify();

Edit This syntax does not work in current versions of Moq. See this question for how to do it as of at least 4.0.10827

Upvotes: 5

Lance Fisher
Lance Fisher

Reputation: 25813

I figured out how to do this. You can can mock protected methods with Moq, and by making a strict mock, you can verify that they were called. Now I can test the base class without having to make any subclasses.

[Test]
public BaseMethod_should_call_correct_child_method()
{
  //strict mocks will make sure all expectations are met
  var testBaseMock = new Mock<TestBase>(MockBehavior.Strict);

  //expect that ChildMethod1() will be called once. (it's protected)
  testBaseMock.Protected().Expect("ChildMethod1")
    .AtMostOnce();

  var testBase = testBaseMock.Object;

  testBase.runMethod1 = true;
  testBase.BaseMethod();

  //make sure the method was called
  testBase.VerifyAll();
}

Upvotes: 4

David Norman
David Norman

Reputation: 19879

It's a bit of a hack, but how about creating a subclass of TestBase that makes ChildMethod1 and ChildMethod public and then Moqing that?

Upvotes: 1

flukus
flukus

Reputation: 1028

It seems like your testing the behaviour rather than the public interface. If this is intended then you could probably look at advice for testing private members.

"Is it possible to create an implemention of TestBase with Moq, call BaseMethod() and verify that ChildMethod was called on the Moq implementation?"

It's sort of possible. But then you would be testing the mock object, not the real object.

Two questions that might steer you in the right direction:

  1. Does the descendatn class return a different value than the base class? If so you can test for that and ignore implimentation details (makes refactoring alot easier too).

  2. Does the descendant class call different methods or different dependencies? If so you can check the dependencies.

Upvotes: 0

Related Questions