Reputation: 946
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.
Upvotes: 3
Views: 2579
Reputation: 3082
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.
Upvotes: 4