سؤال

I'm creating a new application in NancyFx and I'm trying to do Test Driven Development (TDD) So the first features I want to develop are reading and writing to a json file. Now I know this is quite hard to do because it involves httpContext which I obviously can't do unless the application is running.

What I would like to do is mock this so I can create a unit test for reading and writing to a json file. Could anyone show me an example of how I might do this and explain how you have done it?

I have two methods one for reading and one for writing shown below:

ReadToJsonFile Method:

public IEnumerable<T> ReadFile<T>(string fileName)
    {
        try
        {
            var readFile = File.ReadAllText(HttpContext.Current.Server.MapPath(fileName));
            var list = JsonConvert.DeserializeObject<List<T>>(readFile);
            return list;
        }
        catch (Exception ex)
        {
            _logger.LogException(ex);
            return null;
        }
    }

WriteToJsonFile Method:

public bool WriteFile<T>(string fileName, IEnumerable<T> list)
    {
        try
        {
            var listContent = JsonConvert.SerializeObject(list, Formatting.Indented);
            File.WriteAllText(HttpContext.Current.Server.MapPath(fileName), listContent);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogException(ex);
            return false;
        }
    }

Any suggestions would be brilliant, Thanks.

هل كانت مفيدة؟

المحلول

I suggest that you employ an adapter or facade to abstract away from using System.IO static methods:

public class JsonWriter
{
    private readonly IFileSystem _file;
    private readonly HttpContextBase _httpContext;
    private readonly ILog _logger;

    public JsonWriter(
        IFileSystem file, 
        HttpContextBase httpContext,
        ILog logger)
    {
        _file = file;
        _httpContext = httpContext;
        _logger = logger;
    }

    public bool WriteFile<T>(string fileName, IEnumerable<T> list)
    {
        try
        {
            var listContent = JsonConvert.SerializeObject(list, Formatting.Indented);
            _file.WriteAllText(_httpContext.Server.MapPath(fileName), listContent);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogException(ex);
            return false;
        }
    }

}

You'll need an interface like this:

///<summary>Implementors are wrappers for static methods of System.IO.File and System.IO.Directory
///</summary>
public interface IFileSystem
{

    ///<summary>Creates a new file, writes the specified string to the file, then closes the file. If the file already exists, it is overwritten.
    ///</summary>
    ///<param name="path">The file to write to</param>
    ///<param name="contents">The string to write to the file</param>
    void WriteAllText(string path, string contents);

    ///<summary>Creates a new file, writes the specified string to the file, then closes the file. If the file already exists, it is overwritten.
    ///</summary>
    ///<param name="path">The file to write to</param>
    ///<param name="contents">The string to write to the file</param>
    ///<param name="encoding">An <see cref="Encoding"/> object that represents the encoding to apply to the string</param>
    void WriteAllText(string path, string contents, Encoding encoding);

}

And an implementation like this:

///<summary>Replaces the static methods of System.IO.File
///</summary>
public class FileSystem : IFileSystem
{
    ///<summary>Creates a new file, writes the specified string to the file, then closes the file. If the file already exists, it is overwritten.
    ///</summary>
    ///<param name="path">The file to write to</param>
    ///<param name="contents">The string to write to the file</param>
    public void WriteAllText(string path, string contents)
    {
        File.WriteAllText(path, contents);
    }

    ///<summary>Creates a new file, writes the specified string to the file, then closes the file. If the file already exists, it is overwritten.
    ///</summary>
    ///<param name="path">The file to write to</param>
    ///<param name="contents">The string to write to the file</param>
    ///<param name="encoding">An <see cref="Encoding"/> object that represents the encoding to apply to the string</param>
    public void WriteAllText(string path, string contents, Encoding encoding)
    {
        File.WriteAllText(path, contents, encoding);
    }
}

Now you can mock the file methods and the HttpContext in your unit tests.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top