Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
386 views
in Technique[技术] by (71.8m points)

tdd - How do I unit-test saving file to the disk?

I know that it's strongly recommended to run unit-tests in separation from file system, because if you do touch file system in your test, you also test file system itself. OK, that's reasonable.
My question is, if I want to test file saving to the disk, what do I do? As with database, I separate an interface that is responsible for database access, and then create another implementation of this for my tests? Or may be there's some other way?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

My approach towards this is heavily biased on the Growing Object-Oriented Software Guided by Tests (GOOS) book that I just read, but it's the best that I know of today. Specifically:

  • Create an interface to abstract away the file system from your code. Mock it where this class is needed as a collaborator/dependency. This keeps your unit-tests quick and feedback fast.
  • Create integration tests that test the actual implementation of the interface. i.e. verify that calling Save() actually persists a file to disk and has the write contents (use a reference file or parse it for a few things that it should contain)
  • Create an acceptance test that tests the whole system - end to end. Here you may just verify that a file is created - the intent of this test is to confirm if the real implementation is wired / plugged in correctly.

Update for commenter:

If you're reading structured data (e.g. Book objects) (If not substitute string for IEnumerable)

interface BookRepository
{
  IEnumerable<Books> LoadFrom(string filePath);
  void SaveTo(string filePath, IEnumerable<Books> books);
}

Now you can use constructor-injection to inject a mock into the client class. The client class unit tests therefore are fast ; do not hit the filesystem. They just verify that the right methods are called on the dependencies (e.g. Load/Save)

var testSubject = new Client(new Mock<BookRepository>.Object);

Next you need to create the real implementation of BookRepository that works off a File (or a Sql DB tommorrow if you want it). No one else has to know. Write integration tests for FileBasedBookRepository (that implements the above Role) and test that calling Load with a reference file gives the right objects and calling Save with a known list, persists them to the disk. i.e. uses real files These tests would be slow so mark them up with a tag or move it to a separate suite.

[TestFixture]
[Category("Integration - Slow")]
public class FileBasedBookRepository 
{
  [Test]
  public void CanLoadBooksFromFileOnDisk() {...}
  [Test]
  public void CanWriteBooksToFileOnDisk() {...}
}

Finally there should be one/more acceptance tests that exercises Load and Save.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...