c# - 需要帮助确定要编写的单元测试

标签 c# unit-testing testing tdd

我有以下方法并希望编写有效的单元测试,这些单元测试也能很好地覆盖代码路径:

public TheResponse DoSomething(TheRequest request)
{
    if (request == null)
        throw new ArgumentNullException("request");

    BeginRequest(request);

    try
    {
        var result = Service.DoTheWork(request.Data);

        var response = Mapper.Map<TheResult, TheResponse>(result);

        return response;
    }
    catch (Exception ex)
    {
        Logger.LogError("This method failed.", ex);

        throw;
    }
    finally
    {
        EndRequest();
    }
}

该方法使用的 Service 和 Logger 对象被注入(inject)到类构造函数中(未显示)。 BeginRequest 和 EndRequest 在基类(未显示)中实现。 Mapper 是用于对象到对象映射的 AutoMapper 类。

我的问题是什么是好的、有效的方法来为这样的方法编写单元测试,同时提供完整(或有意义的)代码覆盖率?

我是一个测试一个断言原则的信徒,并将 Moq 用于 VS-Test 中的模拟框架(尽管我并没有因为这个讨论而挂断那个部分)。虽然一些测试(比如确保在异常中传递 null 结果)是显而易见的,但我发现自己想知道其他想到的是否有意义;尤其是当他们以不同的方式执行相同的代码时。

最佳答案

从您的帖子/评论来看,您似乎已经知道应该编写哪些测试,并且它与我在第一眼看到您的代码后要测试的内容非常匹配。一些明显的事情开始:

  • 空参数异常检查
  • 模拟服务和记录器以检查是否使用正确的数据调用它们
  • stub 映射器(和潜在的服务)以检查是否实际返回了正确的结果

现在,困难的部分。根据您的基类是否是您有权访问的东西(例如,可以毫不费力地更改它),您可以尝试称为提取和覆盖的方法:

  1. 在基类中将 BeginRequest/EndRequest 标记为虚拟
  2. 在派生类中什么也不做
  3. 引入新的、可测试的类,该类派生自您要测试的类;覆盖基类(BeginRequest/EndRequest)的方法,使它们成为例如。更改一些您稍后可以轻松验证的内部值

代码可能看起来或多或少像这样:

Base 
{
    protected virtual void BeginRequest(TheRequest request) { ... }
    protected virtual void EndRequest() { ... }
}

Derived : Base // class you want to test
{
    // your regular implementation goes here
    // virtual methods remain the same
}

TestableDerived : Derived // class you'll actually test
{
    // here you could for example expose some properties 
    // determining whether Begin/EndRequest were actually called,
    // calls were made in correct order and so on - whatever makes
    // it easier to verify later

    protected override void BeginRequest(TheRequest request) { ... }
    protected override void EndRequest() { ... }  
}

您可以在 Art of Unit Testing 中找到有关此技术的更多信息书,以及Working Effectively with Legacy Code .即使我相信可能有更优雅的解决方案,这个解决方案应该使您能够测试流程并验证 DoSomething 方法中交互的一般正确性。

当您无法访问基类并且无法修改其代码时,问题当然会出现。不幸的是,我没有针对这种情况的“书外”解决方案,但也许您可以在 Derived 中围绕 Begin/EndRequest 创建虚拟包装器,并且仍然使用提取和覆盖 TestableDerived。

关于c# - 需要帮助确定要编写的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5504967/

相关文章:

c# - visual studio 不会将程序集复制到 gac

C# 通过 TCP 使用 SSL 发送请求不起作用

javascript - jQuery .val() 不会生成 'change'

golang test spy 错误地比较相等性

java - 在 Java 中测试使用另一个比较器的比较器的最佳方法是什么?

unit-testing - 集成与单元测试

c# - 获取随机免费打开的端口进行测试

c# - LinqKit Predicate Builder 抛出 TypeLoadException?

Python Unittest2 - 避免在 discover() 中包含 TestCase

简单套接字服务器的 Ruby 单元测试