为单元测试添加代码是不是很糟糕?

Vac*_*ano 20 c# unit-testing

我正在编写一个类来帮助我对代码进行单元测试.它看起来像这样:

/// <summary>
/// Wrapper for the LogManager class to allow us to stub the logger
/// </summary>
public class Logger
{
    private static ILogger _logger = null;

    /// <summary>
    /// This should be called to get a valid logger.
    /// </summary>
    /// <returns>A valid logger to log issues to file.</returns>
    public static ILogger GetLogger()
    {
        if (_logger == null)
          _logger = LogManager.GetLogger("logger");

        return _logger;
    }

    /// <summary>
    /// This is used by unit tests to allow a stub to be used as a logger.
    /// </summary>
    /// <param name="logger"></param>
    /// <returns></returns>
    public static ILogger GetLogger(ILogger logger)
    {
        _logger = logger;
        return _logger;
    }
}
Run Code Online (Sandbox Code Playgroud)

第二种方法仅用于单元测试.我从不打算在我的生产代码中调用它.

这是不好的做法吗?我应该找到另一种不这样做的方法吗?

Chr*_*tte 12

在我看来,这是一个不好的做法.单元测试旨在测试代码的实现,而不是真正影响它.在某些情况下,我发现以一种方式组织我的代码/方法以使其更容易/彻底测试是切实可行的,但是在测试特定用途的类中编写代码是一个不同的故事.

  • 测试驱动设计意味着您的实施受到测试的严重影响.注意,我并不是说这是测试驱动设计的一个特别好的例子. (2认同)

Jef*_*nal 11

通常,仅为便于单元测试而存在的代码隐藏了设计缺陷.

在这种情况下,您隐藏的缺陷是使用全局状态.使用您的记录器的类是秘密依赖它的:除非您阅读它们的源代码,否则您无法告诉他们需要记录器!

这些类应该ILogger在他们的构造函数中需要一个,使他们明白他们需要工作并使它们易于测试.


Jer*_*oen 3

你可以考虑这个:

/// <summary>
/// Wrapper for the LogManager class to allow us to stub the logger
/// </summary>
public class Logger
{
    private static ILogger _logger = null;

    /// <summary>
    /// This should be called to get a valid logger.
    /// </summary>
    /// <returns>A valid logger to log issues to file.</returns>
    public static ILogger Logger
    {
        get
        {
            if (_logger == null)
            {
                _logger = LogManager.GetLogger("logger");
            }
            return _logger
        }
        set
        {
            _logger = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果尚未使用 setter 设置记录器,它将在第一次调用 getter 时设置记录器。