fake directories for .net unit testing - unit-testing

I'm trying to create a unit test for a code similar to this:
foreach (string domainName in Directory.GetDirectories(server.Path))
{
HandleDomainDirectory(session, server, domainName);
}
The problem is that I'm using the System.IO.Directory class in my code.
How can I create a testing method that won't be dependent on any folder I have on my hard disk.
In other words, How can I fake the response of "Directory.GetDirectories(server.Path)"?
(Please note, I do control the "server" object in my class, therefore i can give any path i want)
Thanks.

Rather than calling Directory.GetDirectories(server.Path) directly, you could create an interface like IDirectoryResolver with a single method that takes a path string and returns the list of directories. The class containing your code above would then need a property or field of type IDirectoryResolver, which can be injected through the constructor or a setter.
For your production code, you would then create a new class that implements the IDirectoryResolver interface. This class could use the Directory.GetDirectories method in its implementation of the interface method.
For unit testing, you could create a MockDirectoryResolver class which implements IDirectoryResolver (or use a mocking library to create a mock instance for the interface). The mock implementation can do whatever you need it to do.

You would inject a wrapper class.
public class DirectoryFetcher
{
public virtual List<string> GetDirectoriesIn(string directory)
{
return Directory.GetDirectories(directory);
}
}
And then inject that:
foreach(string directory in _directoryFetcher.GetDirectoriesIn(server.Path))
{
// Whatever
}
You can then Mock that guy at the injection point (this example uses Moq, and constructor injection):
Mock<DirectoryFetcher> mockFetcher = new Mock<DirectoryFetcher>();
mockFetcher.Setup(x => x.GetDirectoriesIn("SomeDirectory")).Returns(new List<string>
{
"SampleDirectory1",
"SampleDirectory2"
});
MyObjectToTest testObj = new MyObjectToTest(mockFetcher.Object);
// Do Test

When communicating with the outside world, such as file system, databases, web services etc. , you should always consider using wrapper classes like the others before me suggested. Testability is one major argument, but an even bigger one is: The out side world changes, and you have no control over it. Folders move, user rights changes, new disk drives appears and old ones are removed. You only want to care about stuff like that in one place. Hence, the wrapper -- let's call it DirectoryResolver like Andy White suggested ealier.
So, wrap your file system calls, extract an interface, and inject that interface where you need to communicate with the file system.

The best solution I've found was to use Moles. The code is very specific, and must do very specific thing. Wrapping it with wrapper class will be redundant. The only reason I needed wrapper class is in order to write tests. Moles allows me to write the tests without any wrapper class :)

Related

How to unit test a class that consumes a web service?

I have a class (lets call it A) that:
In the constructor takes a config and based on it, creates a stub of
a web service and stores a reference to it in a private field.
Has a few methods that call web methods and some stuff inbetween.
I started to create a unit test that:
Creates an instance of a class A with a dummy configuration.
Through reflection it injects the mocked web service stub.
Although that web service has plenty of methods.
Should I mock them all (in every test, with different data)?
Or maybe I should create another layer that encapsulates only the web methods that are being used?
Or there is another approach?
You should create a wrapper interface around your webservice, and make your class under test take a dependency on that interface, rather than directly on the webservice; you can then mock the interface. Only make that interface expose the methods of the webservice that you find interesting. This is known as a facade pattern, and is detailed here.
Without having a clue about what you're testing, aim for something like this:
public interface IWebserviceWrapper
{
Whatever DoStuff(int something);
}
public class WebserviceWrapper : IWebserviceWrapper
{
private WebService _theActualWebservice;
public WebserviceWrapper(Webservice theService)
{
_theActualWebService = theService;
}
public Whatever DoStuff(int something)
{
return _theActualWebservice.DoSomething(something);
}
}
Then your test would look like this (in this case, using MOQ)
public void Test_doing_something()
{
Mock<IWebserviceWrapper> _serviceWrapperMock = new Mock<IWebserviceWrapper>();
_serviceWrapperMock.SetUp(m => m.DoStuff(12345)).Returns(new Whatever());
var classUnderTest = new ClassUnderTest(_serviceWrapperMock.Object);
var result = classUnderTest.Dothings(12345);
Assert.Whatever....
}
Short answer Yes :). Long answer you should use some kind of mocking lib for example: http://code.google.com/p/mockito/ and in your unit test mock the WS stub and pass it to the tested class. That is the way of the force :)
When you unit test a class, you always want to make sure to only test that class and not include its dependencies. To do that, you will have to mock your WS to have it return dummy data when methods are called. Depending on your scenarios, you do not have to mock ALL the methods for each test, I would say only those that are used.
For an example about mocking, you can read this article: http://written-in-codes.blogspot.ca/2011/11/unit-tests-part-deux.html

Include XML as an embedded resource for unit testing?

I have objects that gets initialized by serializing an XML file.
I'm thinking of including the test data in the test project as an embedded resource instead of "hard-coding" the data in the test method itself.
Embedded Hard-coded approach:
[Test]
public void IsMale_CheckIfGenderIsMale_ReturnsTrue()
{
Human human = new Human();
human.Gender = Gender.Male;
Gender expected = Gender.Male;
Assert.IsTrue((human.Gender == expected));
}
XML approach:
[Test]
public void IsMale_CheckIfGenderIsMale_ReturnsTrue()
{
Human human = Human.Initialize("Human_Male.xml");
Gender expected = Gender.Male;
Assert.IsTrue((human.Gender == expected));
}
Which is a better approach?
We often use embedded xml files in our project for testing. Because we want to test the creation of objects using xml.
It is also good practice to separate the creation of objects from the class itself, for example:
Human human = HumanFactory.Create("Human_Male.xml");
The human class would then have a constructor which takes parameters like gender, and can be called from the HumanFactory class. It's a separation of concerns that will keep the logic of your class separate from the mechanism of building it.
And when you need a human object for a test, you can choose either to create it directly or use the factory and create it from xml.
I would also simplify the HumanFactory class further, by giving it an xml string (or Stream) instead of a filename. This can make it easier to test - because you can just include the xml in your test code and not in a file:
Human human = HumanFactory.Create("<human gender="m"></human>");
Assert.AreEqual(human.Gender, Gender.Male);
Otherwise your test depends on either:
the test setup code deploying the "Human_Male.xml" file to the file system, and removing it afterwards. Although Visual Studio test has a nice mechanism to do this (test settings deployment will copy files into the test run folder as part of the test run setup).
Including a path to the embedded resource in your test code. If you should ever restructure your project layout, you will need to change the test code to match. And make sure you use a relative path.
The only problem with external files is that they may change.
My preferred option is to have a series of initialisation functions within the test file that can be called from the test method as and when required. This also makes for easier and quicker reading for others that may pick up your code, or even yourself in six months time.
Another option is to base some of your object classes around an interface/abstract type so that you can mock them (even in your runtime code) by creating a test class instead.
For example (code agnostic):
base abstract class/interface: IHuman IHuman.Gender
property/attribute IHuman.Height property/attribute IHuman.Weight
property/attribute
class HumanMale inherits IHuman HumanMale.Gender overrides IHuman
Gender to return Male.
class HumanFemale inherits IHuman HumanFemale.Gender overrides IHuman
Gender to return Female.
All code then uses IHuman and you can even use a factory to create IHuman types to create a legion of cybermen :)

Mocking an object with Moq, using Ninject when doing UnitTesting

I'm having trouble using Moq in a UnitTesting project with Ninject.
First a few lines about my solution. It contains several projects (BussinesLogic, DAL, Infrastructure...). My goal is to UnitTest the logic i'm using in BussinessLogic project.
The solution is basicly for a windows service, but i've put in the logic so it can be run standalone. I'm using Ninject and i specify weather i want to use the ProductionModule or the TestingModule (windows service uses ProductionModule, console app uses TestingModule)
I'm using a factory pattern to get ninject kernel whenever i need it inside my application.
My TestingModule inherits from NinjectModule where i override the Load() method and there i do the binding. For instance:
Bind<IStorageManager>().To<StubStorageManager>();
I have the StubStorageManager but it's empty. It contains just the declaration of methods from IStorageManager.
The thing i would like to do is (in laymans terms):
Create a unitTest where i would create a new kernel specifying the TestingModule as it's parameter. Then i would like to create a mock object (let's say a mock of IStorageManager) storageManagerMock. Some method in IStorageManager returns a messageObject so i would probably need to mock that too, couse the bussiness logic is doing something based on that messageObject. So i would like to somehow set properties to that message object and then call some businessLogic method on it, so i can see if the logic works correctly.
I hope i didn't complicate it too much.
Please bear with me, i'm completely new to mocking and dependency injection, but am willing to learn.
I doubt you really want to be using Ninject in your tests. The whole point of using ninject is that you can decouple everything. You also want to try and keep everything decoupled from the dependency container itself if possible. Pass it in if you have to, or pass in factories that create the required object and have the container pass in the factory.
I suspect you probably want to do something like this:
public void ATest(){
//create a mock StorageManager
var managerMock = new Mock<IStorageManager>();
//create a mock MessageObject to be used by business logic
var messageObjectMock = new Mock<MessageObject>();
//have the storage manager return the mock message when required
managerMock.Setup(x => x.GetMessageObject()).Returns(messageObjectMock.Object);
//set up message expectations
messageObjectMock.Setup(x => x.ThisValueExpected).Returns(10);
messageObjectMock.Setup(x => x.ThisFunctionShouldBeCalled()).Verifiable("Function not called.");
//thing to test
BusinessLogicObject blo = new BusinessLogicObject(managerMock.Object);
blo.DoTheThingImTesting();
//make sure the business logic called the expected function, or do whatever check you need...
messageObjectMock.Verify();
}

How to unit test file manager class?

I wrote a simple class to manage business objects.
class Manager
{
string[] GetNames();
BObject GetObject(string name);
void Saveobject(BObject obj);
}
It serializes /deserializes the objects as files on a local disk. I wrote Unit tests for the class and run them. That was fine so far. The problem happens when my test were run on build server because of file access permission I was not allowed to write files on the server. It's obvious I cannot test that way.
I think how to unit test this. One approach I can see is to extract an interface and creat a mock object for testing. But I want to test the class itself. How can I do it?
The class presumably calls file system operations File.OpenRead(), File.OpenWrite() etc. (I assume that this is C# due to the camel casing.) Then, you could create an interface for those operations, e.g.:
public interface IFileSystem {
StreamReader OpenRead(string fileName);
StreamWriter OpenWrite(string fileName);
}
and make the constructor of Manager take an instance of IFileSystem. Then, write a (non-mock) class that implements IFileSystem by calling the actual File.OpenRead() and File.OpenWrite() methods and use this one in the production code. In the tests, you use a mock framework, as mentioned by #Digger (my personal preference is Moq, but I haven't tried Rhino Mocks, so I have nothing negative to say about it) to mock out IFileSystem and use the mock to verify that the methods were called with the correct serialized data.
EDIT: Per request, an example in NUnit with Moq (I don't have an IDE here, so it's untested; feel free to correct it):
[Test]
public void BObjectShouldBeSerializedToFile() {
var fileSystemMock = new Mock<IFileSystem>();
var stream = new MemoryStream();
fileSystemMock.Setup(f => f.OpenWrite("theFileNameYouExpect.txt")).Returns(new StreamWriter(stream)).Verifiable();
var manager = new Manager(fileSystemMock.Object);
manager.SaveObject(new BObject(...));
stream.Seek(0, SeekOrigin.Begin);
Assert.That(...); // Perform asserts on the stream contents here
fileSystemMock.Verify(); // Not really necessary, but verify that `OpenWrite` was called
}
It depends on how much logic is contained in your class, in my opinion.
If there's some complicated logic inside your manager, it makes sense to abstract your file operations as per Aasmund's suggestion so that the logic can be tested independently of the file system. I do this when something is finicky enough to warrant the extra dependencies.
On the other hand, if there's very little logic other than calling into your serialization/deserialization code, then it's often acceptable to skip the unit tests and run integration tests that test the full cycle (create a BObject in memory, persist it via calling SaveObject, read it back out using GetObject, ensure that it is equal/equivalent to the one you persisted in the first place).
If your build environment can't run integration tests, then I'd look into setting it up so that it's possible.

Proper application of Mock objects in Unit Testing

I've got a PresenterFactory that creates Presenter classes based on a Role parameter. Specifically, the Role parameter is an external class which I cannot control (IE 3rd party.)
My factory looks something like this:
public class PresenterFactory {
public Presenter CreatePresenter(Role role, ...) {
if (role.IsUserA("Manager")) {
return new ManagerPresenter(...)
}
if (role.IsUserA("Employee")) {
return new EmployeePresenter(...)
}
}
}
I'm stuck on how to write the unit test for this since creating the Role object forces a database access. I thought that I could Mock this object. My test looked like this:
public void TestPresenterFactory()
{
var mockRole = new Mock<Role>();
mockRole .Setup(role=> role.IsUserA("Manager"))
.Returns(true)
.AtMostOnce();
PresenterFactory.CreatePresenter(mockRole.Object, ...);
mockUserInfo.VerifyAll();
}
However I receive an ArguementException:
Invalid setup on a non-overridable member: role=> role.IsUserA("Manager")
I'm not sure where to go and sure could use some course correction. What am I doing wrong?
You can create a wrapper object for Role that has all the same methods and properties, but is mockable, and the default implementation simply returns the underlying Role's implementation.
Then your tests can use the wrapper Role to set up the desired behaviour.
This is often a way to get around concrete classes that really need mocking.
What you want to mock is the creation of a Role object, then pass that mock object into your CreatePresenter method. On the mock you would set whatever properties required to determine what kind of user it is. If you still have dependencies on the database at this point, then you might look at refactoring your Role object.
Consider using a mocking framework that does not impose artificial constraints (such as requirements for methods to be virtual, for classes to not be sealed, etc) on how your code must be written to be mockable. The only example of such that I'm aware of in .NET context is TypeMock.
In Java when using EasyMock extensions you would be able to mock "real" objects and methods, most likely there's equivalent or alternative mock framework that you can use for your purpose