bic
bic

Reputation: 897

Unit Testing - Should all library dependencies be wrapped/mocked

I am writing a class that will read/write Json files (C#).

I am already mocking the file system for unit testing, and I am now wondering if I should also wrap and mock the the serializer object that is being passed into the class on creation.

I understand that the file system has to be mocked, as otherwise I would have to create files for tests and this would make them integration tests.

Should I also be wrapping the serializer in an interface and mocking it? If so, should I also be wrapping/mocking every dependency in other classes that I write? If I am using many methods from an external class wrapping them in interfaces seems like a big time sink.

Edit:

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);
        }
    }
}

In this code, I am creating the JsonSerializer object within the class. This is a dependency, but I am not sure if it should be wrapped/mocked and injected in the class constructor or just left as is. If I wrap it in and interface and find that I need to use more methods from the class, editing the interface itself could become time consuming.

Upvotes: 1

Views: 557

Answers (1)

Nkosi
Nkosi

Reputation: 247088

This is a "it depends" scenario. Mocking/wrapping every dependency might be overkill but that is way too broad to cover in this question.

For this particular case in my opinion and from my experience the serializer code does not need to be abstracted. If you decide to use a different one you can just edit the method without affecting dependents of the class. The Sources class carries out it's single responsibility of providing the source regardless of how it does it. Which is what matters.

That said, I have also had cases where I would have a IJsonSerializer as a dependency. But again it is solely up to you what you choose.

/// <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);
}

where the implementation wrapped what ever JSON API was to be used for the project.

For example

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);
    }
}

The serializer implementation would be up to you. It could take the raw json, a path, etc.

Upvotes: 1

Related Questions