2016-08-18 74 views
2

我正在嘗試爲C#項目創建單元測試,其中我有一個無法修改的外部類。它不從Interface實現,而且方法不是虛擬的。如何在未聲明爲虛擬的外部類中模擬方法

我想模擬從該類的方法返回的結果以及該方法設置的任何類屬性。

所以我必須在外部類

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#將始終調用它聲明的變量的方法,即使它已被初始化爲繼承的變量。

任何有關如何做這個測試和模擬外部類的Process方法的想法?

謝謝

Tim。你可以採取

+2

你不能模仿Moq,除非它是虛擬的,所以你必須編寫一個調用原始代碼的適配器,但用虛擬方法調用它,然後嘲笑那個。 – Crowcoder

+0

我也會質疑嘲笑本身。你在測試這個外部方法中的邏輯嗎?如果你是那麼,爲什麼嘲笑?如果不是,則使用安裝程序返回或調用計數器。 (mockRatioThreadProcessor.SetUp(r => r.Process())。Callback(()=> i ++); ) – Alok

回答

4

一種方法是創建一個圍繞RatioThreadProcessor一個包裝類:

class RatioThreadProcessorWrapper : IThreadProcessor 
{ 
    private readonly RatioThreadProcessor _ratioThreadProcessor; 

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

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

,並注入它(通過裁判IThreadProcessor)爲FundInfoRatioService

但是,值得看看MethodUnderTest方法。這種方法:

  1. 修改的RatioThreadProcessor實例,
  2. 呼叫Process
  3. 獲取了一定的成果,
  4. 是否與結果的東西。

所以你有一種方法可以做四件事。如果您將前三個方法移出方法並且只有(4)的單一責任,那麼您可以傳入一個測試結果對象並以這種方式測試您的方法,將其從RatioThreadProcessor中解耦。

+1

偉大的解決方案。非常感謝。 – TimBunting