2016-03-06 124 views
1

我已經得到了我使用記錄靜態類:包裝靜態類/方法以便進行單元測試?

public static class myLogger 
{ 
    public static ErrorLogging(string input) 
    { 
     //dostuff 
    } 
} 

我使用它的方式是:

public class myClassthatDoesStuff 
{ 
    ... 
    myLogger.ErrorLogging("some error ocurred"); 
    ... 
} 

我怎樣才能起訂量的myLogger類以能夠進行單元測試並確保執行了ErrorLogging方法? 是否可以在構造函數(構造函數注入)中沒有設置任何參數的情況下做到這一點?myClassthatDoesStuff要求在構造函數中沒有參數。

+0

退房微軟的墊片https://msdn.microsoft.com/en-us/library/hh549176 (v = vs.110).aspx – igorushi

+0

要求 Visual Studio Ultimate –

+0

可能的重複[如何嘲笑靜態方法在C#中使用MOQ框架?](http://stackoverflow.com/questions/12580015/how-to-mock -static-methods-in-c-sharp-using-moq-framework) –

回答

2

如果你不能從靜態變爲非靜態類,與非靜態類包起來......

void Test() 
{ 
    string testString = "Added log"; 
    var logStore = new List<string>(); 
    ILogger logger = new MyTestableLogger(logStore); 

    logger.ErrorLogging(testString); 

    Assert.That(logStore.Any(log => log==testString)); 
} 

public interface ILogger 
{ 
    void ErrorLogging(string input); 
} 

public class MyTestableLogger : ILogger 
{ 
    public MyTestableLogger(ICollection<string> logStore) 
    { 
     this.logStore = logStore; 
    } 

    private ICollection<string> logStore; 

    public void ErrorLogging(string input) 
    { 
     logStore.Add(input); 
     MyLogger.ErrorLogging(input); 
    } 
} 

public static class MyLogger 
{ 
    public static void ErrorLogging(string input) 
    { 
     // Persist input string somewhere 
    } 
} 
+0

有沒有可能在構造函數(構造函數注入)中沒有設置任何參數的情況下做到這一點? myClassthatDoesStuff要求在構造函數中沒有參數。 –

+2

@l - '''''' - ''''''''''''*(從來不知道'@'提到可能會變成這樣的折磨......)*你可以肯定地刪除參數......但是,你將如何測試以查看你添加的日誌條目是否存在於數據存儲中? :) –

1

您可以使用微軟的Shims

假設做您的項目名爲ConsoleApplication1
首先轉到您的單元測試項目參考,右鍵單擊包含myClassthatDoesStuff類的程序集,然後選擇「添加僞裝程序集」。

Add Fakes Assembly

與墊片單元測試看起來像:

[TestClass()] 
public class MyClassthatDoesStuffTests 
{ 
    [TestMethod()] 
    public void ImportansStuffTest() 
    { 
     using (ShimsContext.Create()) 
     { 
      bool logCalled = false; 
      ConsoleApplication1.Fakes.ShimmyLogger.ErrorLoggingString = 
       (message) => logCalled = true; 
      new myClassthatDoesStuff().ImportansStuff(); 
      Assert.IsTrue(logCalled); 
     } 
    } 
} 
+0

這是不是vs專業 –

+0

一旦它被稱爲痣,它仍然可用於VS2010 -https://visualstudiogallery.msdn.microsoft.com/b3b41648-1c21-471f-a2b0-f76d8fb932ee/ – igorushi

3

This blog post描述了完全相同的情況 - 你有一箇舊的靜態測井方法,並希望在測試的代碼中使用它。

  • 將靜態類包裝到非靜態類中 - 不僅用於測試,而且用於一般用途。
  • 將新的非靜態類的方法提取到接口中。
  • 無論你依賴靜態類,取決於接口。例如,如果類DoesSomething需要在靜態類中的函數,這樣做:

    public interface ILogger 
    { 
        void ErrorLogging(string input); 
    } 
    
    public class MyClassthatDoesStuff 
    { 
        private readonly ILogger _logger; 
    
        public MyClassthatDoesStuff(ILogger logger) 
        { 
         _logger = logger; 
        } 
    } 
    

這給了你兩個好處:

  1. 您可以單元測試你的舊靜態類(假設它沒有任何狀態,也不依賴於任何狀態)
  2. 您可以使用該靜態類的單元測試代碼(通過刪除對該靜態類的直接依賴)。您可以替換​​與一個模擬的類,就像將錯誤消息添加到列表中的類一樣。

    class StringLogger : List<string>, ILogger 
    { 
        public void ErrorLogging(string input) 
        { 
         Add(input); 
        } 
    } 
    
    var testSubject = new MyClassthatDoesStuff(new StringLogger()); 
    
+0

是否有可能不用在構造函數(構造函數注入)中設置任何參數來做到這一點? myClassthatDoesStuff要求在構造函數中沒有參數。 –

+0

如果你不能把任何東西放在構造函數中,肯定會讓它更難。如果你可以從頭開始使用依賴注入,那麼你就可以控制類的實例化。例如,在沒有依賴注入的情況下,WCF服務類通常在其構造函數中沒有任何東西。 –

+0

斯科特非常感謝你解釋所有這些。說得通 –

1

你可以用Typemock Isolator做到這一點。

它可以讓你避免包裝和接口的所有這一數額,並做簡單:

[TestMethod] 
public void TestLogging() 
{ 
    //Arrange 
    Isolate.WhenCalled(() => myLogger.ErrorLogging("")).CallOriginal(); 

    //Act 
    var foo = new myClassthatDoesStuff(); 
    foo.DoStuff(); 

    //Assert 
    Isolate.Verify.WasCalledWithAnyArguments(() => myLogger.ErrorLogging("")); 
} 
相關問題