Mocking System.IO.Directory operations in Nunit using Rhino mocks

703 views
Skip to first unread message

Mitesh Agrawal

unread,
Aug 5, 2013, 5:01:00 AM8/5/13
to rhino...@googlegroups.com
Hi I have following method in my class and I want to write unit test for it using nunit and rhino mocks. My method moves all the folders from source path to destination path, I am new to NUnit and Rhinomocks and I dont know how to mock System.IO.Directory or System.IO.DirectoryInfo objects. I have tried everything on google.

        public void MoveDirectories() 
        {
            var dirList = (from f in new DirectoryInfo(sourceDir).EnumerateDirectories("*")
                           select f).ToList();

            destinationDir = destinationDir + "//" + newDir;

            foreach (var d in dirList)
            {
                if (GetWeekOfYear(d.CreationTime) == weekNo)
                {
                    if (!Directory.Exists(destinationDir))
                    {
                        Directory.CreateDirectory(destinationDir);
                    }

                    if (!Directory.Exists(destinationDir + "//" + d.Name))
                    {
                        Console.WriteLine("Move Folder  " + d.FullName + " TO " + destinationDir + "//" + d.Name);
                        Directory.Move(d.FullName, destinationDir + "//" + d.Name);
                    }
                }
            }
        }

Here method GetWeekOfYear returns the Week number for a current date or date supplied.
If any one can help me to achieve this. 

Thanks in advance,
Mitz.

Mike Meisinger

unread,
Aug 7, 2013, 12:06:14 AM8/7/13
to rhino...@googlegroups.com
This is a common problem that people will run into; not only from a "mocking" perspective but more from a unit testing perspective.
There are many who would state that you are performing an integration test versus a unit test and other who would tell you to not attempt to test "infrastructure concern."

From a mocking perspective... some classes just simply cannot be mocked or (better phrased) don't lend themselves to being mocked.
For File and Directory concerns, I have seen some that will attempt to create a wrapper around this functionality to enable (or promote) unit testing. Your mileage will vary on this... personally I find it a bad practice.

There are alternative options including allowing this concern to be handled in an integration test and not a unit test.
The alternatives, however, are based on what it is that you are actually hoping to achieve with the unit test. Are you trying to test GetWeekOfYear or that the files/directories are handled correctly?

Dino B.

unread,
May 19, 2017, 1:38:05 AM5/19/17
to Rhino.Mocks
Hi Mitesh,
I am trying to figure out similar but what I am finding so far is following:
1. A unit test should not touch the system, so any registry, IO, service, database, etc calls fall into integration tests rather than unit tests
2. So, the way I understand this is done is to create an interface defining what functionality is expected, and a class implementing that interfaced.  Then your unit test will mock the interface, while your real code will instantiate the class.  As an example, I have added code from a dummy little app which does similar with registry.

namespace ConsoleRhinoApp.RegistryActions
{
    /// <summary>
    /// Interface that can be used with both real project and unit tests.
    /// </summary>
    public interface IRegistryActions
    {
        string ReadValue(string path, string key);
        bool WriteValue(string path, string key, string newSubKey, string value);
    }
}

namespace ConsoleRhinoApp.RegistryActions
{
    /// <summary>
    /// Class to write / read registry. 
    /// Implements IRegistryActions interface we can use in real project or unit tests.
    /// </summary>
    public class RegistryActions : IRegistryActions
    {
        public string ReadValue(string path, string key)
        {
            var val = (string)Registry.LocalMachine.OpenSubKey(path).GetValue(key);
            return val;
        }

        public bool WriteValue(string path, string key, string newSubKey, string value)
        {
            RegistryKey rt = null;
            using (rt = Registry.LocalMachine.OpenSubKey(path, RegistryKeyPermissionCheck.ReadWriteSubTree))
            {
                using (var sdp = rt.CreateSubKey(key))
                {
                    sdp.SetValue(newSubKey, value);
                }
            }
            return rt != null;
        }
    }
}


/// <summary>
/// This simmulates a real project.
/// REGISTRY KEY: HKLM\SOFTWARE\WOW6432Node\Mine\Location
/// If key does exist, it will add another key "RhinoTest".
/// Under this key, it will add new property "SomeDummyProperty"
/// And it will set this property to "Some dummy value"
/// </summary>
namespace ConsoleRhinoApp
{
    public class Program
    {
        static void Main(string[] args)
        {
            string path = @"SOFTWARE\WOW6432Node\Mine\Location";
            string key = "RhinoTest";
            string newSubKey = "SomeDummyProperty";
            string value = "Some dummy value";

            // Create instance of class that reads/writes registry and pass it into class that uses it.
            IRegistryActions ra = new RegistryActions.RegistryActions();
            ExampleClass ec = new ExampleClass(ra);
            if (ec.WriteValue(path, key, newSubKey, value))
            {
                Console.WriteLine(string.Format("Created new registry value"));
                string newValue = ec.ReadValue(path + "\\" + key, newSubKey);
                Console.WriteLine(string.Format("New registry value is \'{0}\'.", newValue));
            }
            Console.ReadKey();
        }
    }
}


And here is unit test

using System;
using NUnit.Framework;
using Rhino.Mocks;
using SystemWrapper.Microsoft.Win32;
using ConsoleRhinoApp.RegistryActions;

namespace UnitTestProject
{
    [TestFixture]
    public class UnitTest1
    {
        string path = @"SOFTWARE\WOW6432Node\Mine\Location";
        string key = "RhinoTest";
        string newSubKey = "SomeDummyProperty";
        string value = "Some dummy value";

        [Test]
        public void Test_RegistryActions_generate_stub()
        {
            // Dynamically create a class that implements IRegistryAccess
            var stub = MockRepository.Mock<IRegistryActions>(); // GenerateStub<IRegistryActions>();

            var env = MockRepository.Mock<OperatingSystem>();
            env.Stub(s => s.Platform).Return(PlatformID.Win32NT);
            env.AssertWasCalled(s => s.Version);

        }

        [Test]
        public void Test_RegistryActions_Write_should_return_true()
        {
            var stub = MockRepository.Mock<IRegistryActions>(); // GenerateStub<IRegistryActions>();

            bool expected = true;
            bool actual = true;

            stub.Stub(s => s.WriteValue(path, key, newSubKey, value)).Return(expected);
            stub.WriteValue(path, key, newSubKey, value).Equals(actual);
            stub.AssertWasCalled(s => s.WriteValue(path, key, newSubKey, value));
            Assert.AreEqual(expected, actual);

            // Below is way to do Rhino's built in implementation, I use here our own implmentation which is RegistryActions
            //IRegistryKeyWrap keyMock = MockRepository.GenerateMock<IRegistryKeyWrap>();
            //keyMock.Stub(s => s.OpenSubKey(path + "\\" + key + "\\" + newSubKey, true)).Equals(true);
            //keyMock.Stub(s => s.SetValue(newSubKey, value));
            //keyMock.Stub(s => s.GetValue(newSubKey)).Return(value);
        }

        [Test]
        public void Test_RegistryActions_Read_should_read_expected_value()
        {
            var stub = MockRepository.Mock<IRegistryActions>(); // GenerateStub<IRegistryActions>();

            string expected = value;
            string actual = value;

            stub.Stub(s => s.ReadValue(path + "\\" + key, newSubKey)).Return(expected);
            stub.ReadValue(path + "\\" + key, newSubKey).Equals(actual);
            stub.AssertWasCalled(s => s.ReadValue(path + "\\" + key, newSubKey));
            Assert.AreEqual(expected, actual);
        }
    }
}


Note that my unit test has reference to:
1. SystemWrapper v.0.4.0 by Vadim Kreyinin
2. RhinoMocks v.4.0.0-alpha3 by meisinger, ayende
 
Hope this helps, cheers
Reply all
Reply to author
Forward
0 new messages