2017-08-25 70 views
1

我在寫一個將讀取/寫入Json文件(C#)的類。單元測試 - 是否應該包裝/模擬所有庫依賴關係

我已經在模擬單元測試的文件系統了,現在我想知道是否我也應該包裝並模擬在創建時傳遞到類中的序列化程序對象。

我知道文件系統必須被模擬,否則我將不得不創建文件進行測試,這將使他們進行集成測試。

我是否應該在界面中包裝串行器並嘲笑它?如果是這樣,我是否也應該包裝/嘲笑我編寫的其他類中的每個依賴項?如果我使用外部類中的許多方法,將它們包裝在界面中似乎是一個很大的時間。

編輯:

public class Sources 
{ 
    private readonly IDirectory _directory; 
    private readonly IFile _file; 

    public Sources(IDirectory directory, IFile file) 
    { 
     _directory = directory; 
     _file = file; 
    } 

    public LibrarySource GetSource(string filePath) 
    { 
     using (var streamReader = _file.OpenText(filePath)) 
     using (var jsonTextReader = new JsonTextReader(streamReader.StreamReaderInstance)) 
     { 
      JsonSerializer serializer = new JsonSerializer(); 
      var sourceDto = serializer.Deserialize<LibrarySourceDto>(jsonTextReader); 
      return SourceMapper.Map(sourceDto); 
     } 
    } 
} 

在這段代碼中,我創建的類中JsonSerializer對象。這是一個依賴項,但我不確定它是否應該被包裝/模擬並注入到類構造器中,還是保持原樣。如果我將它封裝在接口中,並發現我需要使用更多類的方法,那麼編輯接口本身可能會耗費大量時間。

+0

這是一個「取決於」情況。嘲笑/包裝每一個依賴可能是過度的,但是這個問題太廣泛了。試着用[mcve]縮小你的問題,讓我們看看社區是否可以幫助你。 – Nkosi

+0

在我看來,根據我的經驗,序列化程序代碼不需要被抽象化。如果你決定使用不同的方法,你可以編輯該方法而不影響該類的依賴者。也就是說,我還有一些情況,我會將IJsonSerializer作爲依賴項。但是,這又取決於你選擇什麼。 – Nkosi

回答

1

這是一個「取決於」情況。嘲笑/包裝每一個依賴可能是過度的,但是這個問題太廣泛了。

在我看來這個特殊情況和我的經驗,序列化代碼不需要被抽象。如果你決定使用不同的方法,你可以編輯該方法而不影響該類的依賴者。 Sources類承擔提供源的單一職責,無論它如何實現。哪個是重要的。

這就是說,我也有案件,我會有一個IJsonSerializer作爲依賴。但是,這又取決於你選擇什麼。

/// <summary> 
/// Provides JSON Serialize and Deserialize. 
/// </summary> 
public interface IJsonSerializer : ISerializer { 

} 

/// <summary> 
/// Serialization interface that supports serialize and deserialize methods 
/// </summary> 
public interface ISerializer { 
    /// <summary> 
    /// Serialize the specified object into a string 
    /// </summary> 
    /// <param name="obj">object to serialize</param> 
    string Serialize(object obj); 
    /// <summary> 
    /// Deserialize a string into a typed object 
    /// </summary> 
    /// <typeparam name="T">type of object</typeparam> 
    /// <param name="input">input string</param> 
    T Deserialize<T>(string input); 
} 

其中的實現包裹了什麼JSON API將用於該項目。

例如

public class Sources { 
    private readonly IDirectory _directory; 
    private readonly IFile _file; 
    private readonly IJsonSerializer serializer; 

    public Sources(IDirectory directory, IFile file, IJsonSerializer serializer) { 
     _directory = directory; 
     _file = file; 
     this.serializer = serializer; 
    } 

    public LibrarySource GetSource(string filePath) { 
     var sourceDto = serializer.Deserialize<LibrarySourceDto>(_file.ReadAllText(filePath)); 
     return SourceMapper.Map(sourceDto); 
    } 
} 

的串行實施將取決於你。它可能需要原始json,路徑等。

相關問題