Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing File I/O

Reading through the existing unit testing related threads here on Stack Overflow, I couldn't find one with a clear answer about how to unit test file I/O operations. I have only recently started looking into unit testing, having been previously aware of the advantages but having difficulty getting used to writing tests first. I have set up my project to use NUnit and Rhino Mocks and although I understand the concept behind them, I'm having a little trouble understanding how to use Mock Objects.

Specifically I have two questions that I would like answered. First, what is the proper way to unit test file I/O operations? Second, in my attempts to learn about unit testing, I have come across dependency injection. After getting Ninject set up and working, I was wondering whether I should use DI within my unit tests, or just instantiate objects directly.

like image 232
Shaun Hamman Avatar asked Oct 06 '09 21:10

Shaun Hamman


People also ask

What is a unit test file?

Unit tests are typically automated tests written and run by software developers to ensure that a section of an application (known as the "unit") meets its design and behaves as intended. In procedural programming, a unit could be an entire module, but it is more commonly an individual function or procedure.

What should I name unit test file?

The name of your test should consist of three parts: The name of the method being tested. The scenario under which it's being tested. The expected behavior when the scenario is invoked.

What is unit testing in UI?

Unit tests are back-end tests, they can check that a calculation is correct, but they can't verify that the results display correctly to your user. And what about problems like unreadable color combinations, incorrect icons, or missing or mislabeled fields? You need UI testing to catch those problems.

How do you prepare unit testing documents?

Unit Test Plan and Unit Test Cases should be prepared by the Developer (Coder) and verified by the Design Lead. Indicate the planned Code Coverage (Statement and Branch) in Unit Test Plan. Unit Testing should be carried out based on the approved Unit Test Plan document. Developer should conduct Unit Testing.


2 Answers

There isn't necessarily one thing to do when testing the file system. In truth, there are several things you might do, depending on the circumstances.

The question you need to ask is: What am I testing?

  • That the file system works? You probably don't need to test that unless you're using an operating system which you're extremely unfamiliar with. So if you're simply giving a command to save files, for instance, it's a waste of time to write a test to make sure they really save.

  • That the files get saved to the right place? Well, how do you know what the right place is? Presumably you have code that combines a path with a file name. This is code you can test easily: Your input is two strings, and your output should be a string which is a valid file location constructed using those two strings.

  • That you get the right set of files from a directory? You'll probably have to write a test for your file-getter class that really tests the file system. But you should use a test directory with files in it that won't change. You should also put this test in an integration test project, because this is not a true unit test, because it depends on the file system.

  • But, I need to do something with the files I get. For that test, you should use a fake for your file-getter class. Your fake should return a hard-coded list of files. If you use a real file-getter and a real file-processor, you won't know which one causes a test failure. So your file-processor class, in testing, should make use of a fake file-getter class. Your file-processor class should take the file-getter interface. In real code, you'll pass in the real file-getter. In test code you'll pass a fake file-getter that returns a known, static list.

The fundamental principles are:

  • Use a fake file system, hidden behind an interface, when you're not testing the file system itself.
  • If you need to test real file operations, then
    • mark the test as an integration test, not a unit test.
    • have a designated test directory, set of files, etc. that will always be there in an unchanged state, so your file-oriented integration tests can pass consistently.
like image 109
Ryan Lundy Avatar answered Oct 14 '22 01:10

Ryan Lundy


Check out Tutorial to TDD using Rhino Mocks and SystemWrapper.

SystemWrapper wraps many of System.IO classes including File, FileInfo, Directory, DirectoryInfo, ... . You can see the complete list.

In this tutorial I'm showing how to do testing with MbUnit but it's exactly the same for NUnit.

Your test is going to look something like this:

[Test] public void When_try_to_create_directory_that_already_exists_return_false() {     var directoryInfoStub = MockRepository.GenerateStub<IDirectoryInfoWrap>();     directoryInfoStub.Stub(x => x.Exists).Return(true);     Assert.AreEqual(false, new DirectoryInfoSample().TryToCreateDirectory(directoryInfoStub));      directoryInfoStub.AssertWasNotCalled(x => x.Create()); } 
like image 44
Vadim Avatar answered Oct 14 '22 03:10

Vadim