How to create test code using .Net IO classes?

I want to create a single testable code that mocks the calls to the .Net System.IO classes, so I really can unit test instead depending on the file system. I use the SystemWrapper classes to wrap around BCL classes.

I am trying to get a simple work example to see if a file exists.

The problem I am facing is that dependency injection in the class does not work, because creating dependencies (via StructureMap ) requires knowing which constructor parameter should pass, which will not be available at that time, there is also no default constructor.

code example:

// don't want to create dependency here like so //IFileInfoWrap fileInfoWrap = new FileInfoWrap(filename); // using service locator (anti-pattern?!) since it can't be // injected in this class var fileInfoWrap = ObjectFactory.GetInstance<IFileInfoWrap>( new ExplicitArguments(new Dictionary<string, object> { {"fileName", filename} })); Console.WriteLine("File exists? {0}", fileInfoWrap.Exists); 

I donโ€™t like that the dependency is not introduced, ObjectFactory should not be here (but I donโ€™t see another way to create this). ExplicitArguments makes it messy, and the argument name is a magic string.

In order to make this work, the StructureMap configuration class needs to know which constructor I want to use (I just started with StructureMap, so this may not be the right way to configure it):

 ObjectFactory.Initialize(x => { x.Scan(scan => { scan.AssembliesFromPath("."); scan.RegisterConcreteTypesAgainstTheFirstInterface(); scan.WithDefaultConventions(); }); // use the correct constructor (string instead of FileInfo) x.SelectConstructor(() => new FileInfoWrap(null as string)); // setting the value of the constructor x.For<IFileInfoWrap>() .Use<FileInfoWrap>() .Ctor<string>("fileName") .Is(@"."); }); 

Has anyone found a better solution for creating testable code for the System.IO classes? I know that part of the problem is developing the System.IO classes.

+6
source share
1 answer

The approach that I have used very successfully is to collapse my own proxy types for the types found in System.IO and other parts of FCL. For instance. I want to depend on System.IO.File . I create a library called System.IO.Proxies and add a specific File type and IFile interface. The IFile interface provides elements that are equivalent to all that I need from System.IO.File , and a particular type implements these elements without doing anything other than calling the forwarding method to System.IO.File . System.IO.Proxies excluded from unit testing and code coverage. In my consumer build, I only take dependency on System.IO.Proxies , and in particular, I take the dependency on IFile . This way, I can easily mock this dependency and get 100% code coverage for my build assembly.

(Note that this is a more appropriate version of my more general answer to the previous question.)

+5
source

Source: https://habr.com/ru/post/905389/


All Articles