Mocking a FileStream with NSubstitute

2,218 views
Skip to first unread message

Roman Griesser

unread,
May 18, 2016, 2:49:23 AM5/18/16
to NSubstitute
Hello together,

i am new to NSubstitute.
I have a class that loads data out of xml files.


        public T LoadData<T>(string fileName)
        {
            T data;

            fileName = $@"{this.WorkingPath}\{fileName}";

            Log.Info($"Loading data from: {fileName}");
            using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
            {
                var xmlData = new XmlSerializer(typeof (T));
                data = (T) xmlData.Deserialize(stream);
                stream.Close();
            }

            return data;
        }

I try to mock the FileStream but im not able to get the job done.

The FileStream always calls for an existing file and throws an exception.

Is it even possible to do this?

Thanks

David Tchepak

unread,
May 18, 2016, 3:10:11 AM5/18/16
to nsubs...@googlegroups.com
Hi Roman,

Even if possible (FileStream has virtual methods I think, which is one precondition for mocking, but I'm not sure what it does in the constructor), I would not recommend it. I find faking out details of a chatty interface like this ends up giving me very little confidence that my code actually works. It is only a useful test if my fake works just like the real thing, in which case why not use the real thing directly?

What would you like to focus on for your test here? If you just want some confidence that it works as expected, I think I would write a test using a real file. This can be a bit painful to set up (getting working directories for the test correct etc), but is probably the best way to demonstrate that the code is doing roughly what you expect.

If for some reason you really wanted to use mocking for this (say, the file system overhead was too much, which seems unlikely but let's pretend), you could inject a dependency for loading the stream into the class:

        IFileReader fileReader; // where IFileReader is your own interface, injected via the constructor
        public T LoadData<T>(string fileName)
        {
            T data;
            fileName = $@"{this.WorkingPath}\{fileName}";
            Log.Info($"Loading data from: {fileName}");
            using (var stream = fileReader.GetStream(fileName)) // get the stream from the dependency
            {
                ...
            }
            return data;
        }

We could then stub out `GetStream` to return an in-memory stream or similar in your test:

    var fileReader = Substitute.For<IFileReader>();
    var classUnderTest = new MyClass(fileReader);
    fileReader.GetStream("workingdir\\myfile").Returns(inMemoryStream);
    var result = classUnderTest.LoadData<Sample>("myfile");
    // assert result is as expected

But I don't think this is giving us much benefit over keeping your code as-is and using a real file and real FileStream.

Hope this helps.
Regards,
David

    


--
You received this message because you are subscribed to the Google Groups "NSubstitute" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nsubstitute...@googlegroups.com.
To post to this group, send email to nsubs...@googlegroups.com.
Visit this group at https://groups.google.com/group/nsubstitute.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages