I’m looking for some advice for unit-testing in a manner that doesn’t leave “test hooks” in place in production code.
Let’s say I have a static class (VB.NET Module) named MethodLogger who has a “void WriteEntry(string Message)” method that is intended to write the calling method and a message to a log file on disk. The actual target of WriteEntry() can be diverted to a fake implementation of IMethodLogger for running unit tests, and for all other cases it should call the real implementation of IMethodLogger.
Here’s a rough-cut of what I’ve whipped up so far, and I like the approach–but in some quick tests it raises some questions and doubts:
[InternalAttributesVisibleTo("MethodLogger.Tests")]
internal static class MethodLogger
{
public void WriteEntry(string message)
{
LogWriter.WriteEntry(message);
}
private IMethodLogger LogWriter
{
get;
set;
}
#if DEBUG
internal void SetLogWriter(IMethodLogger logger)
{
LogWriter = logger;
}
#endif
}
Here’s my specific questions:
-
This tightly couples the unit tests to running against the DEBUG build; when I run unit tests though it appears that it doesn’t specifically rebuild the assembly under test in DEBUG–is it possible to do so?
- Would I ever want to run the unit tests against a non-debug build? Off the top of my head I see less value–but would there be?
-
Would it be possible for me to use a custom pre-compiler flag like “TEST” in lieu of “DEBUG”? How would I go about telling Visual Studio to always rebuild the target with this flag for testing to ensure my hooks / seams are available?
I don’t like the idea of not being able to run the tests against the real production binaries, personally.
Could you not just mark the setter as “obsolete” and disable the obsolete warning in your test code? Along with suitable documentation, that should stop production code from accidentally calling it, but still make it available to tests.
However, to address your actual questions: