2017-08-25 69 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,路径等。

相关问题