0

I've been designing and developing a very scalable logging library for a while.

The main goal of this library is pretty simple. Like many others projects, a simple goal does not mean a simple way the achieve it. Days after designing the API and the main architecture, this library seems to have a quite large engine on the background.
Most of this engine is based on streams, disk-flushing, text formatting, buffering and, of course, file and directories interaction; nothing surprising, indeed.

After coding a bit, I realized I never thought about the test design. Well, I trusted it to be easier than it seems.
For the sake of explanation, I point out that I am developing in C# (v8.0) with a .NET Standard (v2.1) environment. I prefer the lack of third parties libraries (I will develop separate packages for other libraries or frameworks integration, such as ASPNET, Autofac, and so on...).

The point of the question is, since I am almost bound to the System.IO environment that .NET exposes, I don't know how to really test my librarie's features.

Well, there are lots of methods, classes or modules that are easy to test (I am trying to apply a TDD strategy). But there are many others services left to this, where they interact directly with the file system.

For a testing development environment, I use NUnit with FakeItEasy.

The point is, how can I test and mock those classes, methods and modules that are totally bounded by the machine file system?

Thanks.

1 Answer 1

2

Shims

You'll need to introduce a Shim between your unit testable code and the integration code.

A good example of this would be the SQLite database engine that uses a virtual file system shim. This has several benefits:

  • Everything above the shim can be unit tested using an in memory vfs.
  • Everything below the shim can be tested by a single suit of tests that round trip reads/writes to and from the file system.
    • though some extra dedicated tests don't hurt.
  • The system can target different backend storage technologies very easily (a in memory, the standard system.io, or some other method like a db).

Additionally the shim only needs to be as complex as your requirements are. Don't need the ability to delete files? then the shim does not have to have that ability.

If you had some form of scripting, this would also serve to enhance security as you are effectively reducing and limiting certain operations that would have been exposed had you exposed the underlying io library directly.

2
  • Hi, @Kain0_0. Thanks for your answer. Do you know any library to mock this up? I mean, what would make perfect to me is call Directory.CreateDirectory() (for example), but actually this does not create an actual directory, but my Test libreary takes as it was. Commented Apr 16, 2020 at 13:03
  • 1
    There probably is a way to do this using a third-party tool. But the point of a shim is to provide exactly those primitives you require no more, and no less. The primitives may not even be createDirectory() and OpenFile() but instead openLog(). Using that option your main logging code main not need to understand filesystems at all, just a connection string that looks like a path, or an sql db connection, or something else. Commented Apr 17, 2020 at 0:27

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.