如何模拟未声明为虚拟的外部 class 中的方法

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

我正在尝试为 C# 项目创建单元测试,我有一个无法修改的外部 class。它不从接口实现,方法不是虚拟的。

我想模拟从这个 class 的方法返回的结果以及该方法将设置的任何 class 属性。

所以我在外部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
    }

我测试的代码是这样的:

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
    }

为了测试它,我想做类似的事情:

  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
  }

我遇到的问题是始终调用基本 Process 方法,而不是我想调用的模拟方法。

我认为这是因为 C# 将始终调用它声明的变量的方法,即使它已被初始化为继承的方法。

关于如何进行此测试并模拟外部 class 的 Process 方法的任何想法?

谢谢

时间

您可以采取的一种方法是围绕 RatioThreadProcessor:

创建包装器 class
class RatioThreadProcessorWrapper : IThreadProcessor
{
    private readonly RatioThreadProcessor _ratioThreadProcessor;

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

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

并将其(通过对 IThreadProcessor 的引用)注入 FundInfoRatioService.

但是,MethodUnderTest 方法值得一看。此方法:

  1. 修改RatioThreadProcessor
  2. 的实例
  3. 调用 Process
  4. 得到一些结果,
  5. 对结果做些什么。

所以你有一个方法可以做四件事。如果您将前三个移出该方法并让它承担 (4) 的单一职责,那么您可以传入一个测试结果对象并以这种方式测试您的方法,将其与 RatioThreadProcessor.[= 解耦18=]