Recently I ran into a dilema of that I needed to unit test a method that had a call to a built in .net methods of System.IO.File.Exists(), and as unit tests don’t have access to the file system as soon as the method got to System.IO.File.Exists() it would error out.
How I fixed this was to simply implement an interface over a custom class that will simply run System.IO.File.Exists() and then in the unit test mock that interface to return true.
1 2 3 4 5 |
// the interface public interface IFileSystem { bool FileExists(string fileName); } |
1 2 3 4 5 6 7 8 |
// the implementation public class FileSystem : IFileSystem { public bool FileExists(string fileName) { return System.IO.File.Exists(fileName); } } |
Now to use this method in our controller instead of using System.IO.File.Exists()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
private IFileSystem _fileSystem; public MyController() { _fileSystem = new FileSystem(); } // used for dependancy injection from a unit test public MyController(IFileSystem fileSystem) { _fileSystem = fileSystem } public ActionResult MyAction(string file) { _fileSystem.FileExists(file); } |
This is simply using manual dependany injection, and you could do this automated via e.g. Autofac / Ninject etc
Then you would use this in the controller action via _fileSystem.FileExists();
Now in your unit test you will need to mock / fake the call to FileExists to return what you need of true or false. You can achive this by using a mocking framework called Moq.
Once Moq is installed you can mock the call by the following:
1 2 3 |
private Mock<IFileSystem> _fileSystemMock; _fileSystemMock = new Mock<IFileSystem>(); |
This created a new mock object from the IFileSystem interface.
Then to mock the method within that interface / mocked object, you will need this
_fileSystemMock.Setup(o => o.FileExists(It.IsAny<string>())).Returns(true);
This simply says any call of FileExists witin the _fileSystemMock object, don’t go into and return true.
Then to inject this into the controller you would write
1 2 3 |
var controller = new MyController(_fileSystemMock.Object); var result = controller.ActionMethod(); |
No Comments