TimBunting
TimBunting

Reputation: 542

How can I Mock a method in an external class that is not declared as virtual

I am trying to create a Unit Test for a C# project where I have an external class that I cannot modify. It does not implement from Interface and methods are not virtual.

I want to mock the results coming back from a method of this class and any class properties that the method would set.

So I have in external class

 public class RatioThreadProcessor {
    public SqlString dbName;        
    public List<Instrument> units;
    public Results Results;
    etc
    public void Process() {

        // Does stuff 
        // I want this to be called for real but not in my test case
    }

The code I am testing is like this:

public class FundInfoRatioService
{
    public RatioThreadProcessor ratioThreadProcessor;

    public FundInfoRatioService()
    {
        ratioThreadProcessor = new RatioThreadProcessor();
    }

    public MethodUnderTest() 
    {
       ratioThreadProcesor.dbName = "as";
       ratioThreadProcessor.Process();
       var results = ratioThreadProcessor.Results;
       // important logic I want to test
    }

and to test it I wanted to do something like:

  public class MockRatioThreadProcessor : RatioThreadProcessor
  {
       public new void Process()
       { 
           // mock Logic
           // I want this to be called in my test case
       }
  }      

  private Mock<RatioThreadProcessor> mockRatioThreadProcessor;
  public void SetUp()
  {
      mockRatioThreadProcessor = new Mock<MockRatioThreadProcessor();
      mockRatioThreadProcessor.SetUp(r => r.Process());
  }
  public void TestMethod()
  {
      var fundInfoRatioService = new FundInfoRatioService(null);          
      fundInfoRatioService.ratioThreadProcessor = mockRatioThreadProcessor.Object;
      fundInfoRatioService.MethodUnderTest();
      // assert results
  }

The problem that I have is that the base Process method is always called and not the mocked one I wanted to have called.

I think its because C# will always call the method of the variable that it is declared as, even though it has been initialised to the inherited one.

Any idea on how I can do this test and mock the Process method of the external class?

Thanks

Tim.

Upvotes: 3

Views: 1898

Answers (1)

David Arno
David Arno

Reputation: 43254

One approach you can take is to create a wrapper class around RatioThreadProcessor:

class RatioThreadProcessorWrapper : IThreadProcessor
{
    private readonly RatioThreadProcessor _ratioThreadProcessor;

    public RatioThreadProcessorWrapper ()
    {
        _ratioThreadProcessor = new RatioThreadProcessor();
    }

    public Process() => ratioThreadProcessor.Process();
    ...
}

And inject it (via a ref to IThreadProcessor) into FundInfoRatioService.

However, it's worth looking at the MethodUnderTest method. This method:

  1. Modifies the instance of RatioThreadProcessor,
  2. Calls Process,
  3. Gets some results,
  4. Does something with the results.

So you have one method that does four things. If you move the first three out of the method and just have it have the single responsibility of (4), then you can pass in a test results object and test your method that way, decoupling it from RatioThreadProcessor.

Upvotes: 5

Related Questions