Normally we use Debug.Assert() for code contracts. To stop the Debug.Assert() statements from activating during unit tests, add the following to te unit tests application config file ("App.Config"):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.diagnostics>
<assert assertuienabled="false"/> <!-- Disable Debug.Assert() when running unit tests in debug mode. -->
</system.diagnostics>
</configuration>
Following is a code contract type class that can make code assertions without throwing an Assert dialog during an NUnit test. Also the code contracts will be logged in release. A potential product failure in the field could be traced back to a code contract failure.
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Common.CodeContracts
{
/// <summary>
/// A simple code contract class to replace Debug.Assert(). It can be used in release
/// and will log code contract failures to the Trace output window.
/// </summary>
public static class RuntimeCodeContract
{
// Switch on the Debugger.Break when required
public static bool DebuggerBreakOnFailure { get; set; } = false;
public static void Requires(bool condition,
string message,
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0)
{
if (!condition)
{
var msg = $"Code contract failure detected: \"{message}\" in member \"{member}\" on line {line} in file \"{file}\"";
Trace.TraceError(msg);
if (DebuggerBreakOnFailure)
{
Debugger.Break(); // Use the call stack window to find the invoker location
}
//throw new InvalidOperationException(msg);
}
}
public static void RequiresArgument(bool condition,
string paramName,
string message = "",
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0)
{
if (!condition)
{
var msg = $"Argument requirement failure detected: {message} \"{paramName}\" in member \"{member}\" on line {line} in file \"{file}\"";
Trace.TraceError(msg);
if (DebuggerBreakOnFailure)
{
Debugger.Break(); // Use the call stack window to find the invoker location
}
//throw new ArgumentException(message, paramName);
}
}
public static void RequiresArgumentNotNull(object parameter,
string paramName,
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0)
{
if (parameter == null)
{
var msg = $"Argument {paramName} was null in member {member} on line {line} in file {file}";
Trace.TraceError(msg);
if (DebuggerBreakOnFailure)
{
Debugger.Break(); // Use the call stack window to find the invoker location
}
//throw new ArgumentNullException(msg, paramName);
}
}
}
}
It is also a good example of using the compiler attributes "CallerFilePath", "CallerMemberName", and "CallerLineNumber" for diagnostics.