【问题标题】:How do I test parent methods?如何测试父方法?
【发布时间】:2015-03-16 03:57:42
【问题描述】:

假设我有一个如下所示的界面:

interface IMyAPIService
{ 
    List<Order> GetOrders();    
}

还有一个实现它的类:

class MyAPIService : IMyAPIService
{
    public List<Order> GetOrders() {}
    public bool Login() {}
}

登录调用外部服务。我可以模拟外部服务,因此测试登录没问题。

但是,GetOrders 必须先调用 Login,然后才能执行它需要执行的操作。

我希望能够测试 GetOrders 在登录错误时也会返回错误,但我无法模拟登录,因为它是同一类的成员。我可以模拟 Login 调用的外部服务并确保它返回错误,然后我知道 Login 会返回错误,但我不确定这是否是正确的方法。

我应该只测试 IMyAPIService 中的接口方法而不是 MyAPIService 中的所有公共方法吗?那我该如何测试登录呢?

【问题讨论】:

  • “我可以模拟 Login 调用的外部服务并确保它返回错误”——这是一种有效的测试方式。
  • 只有“GetOrders”才会调用登录以便我可以测试它时,是否可以公开登录?
  • 如果逻辑上不应该公开,您不必独立测试它。在这种情况下,它是另一个公共函数的辅助函数,因此请测试公共函数,但请确保测试私有辅助函数的所有可能输出。如果您看到私有函数变得非常复杂(许多可能的结果、依赖项等),这表明它可能应该是一个单独的类,当然您将自己彻底测试该类。

标签: c# .net unit-testing tdd


【解决方案1】:

为类的公共接口编写测试。如果您的程序中没有代码会在您的 MyAPIService 上调用 Login 方法,那么它就没有理由出现在您的类的公共接口上。

根据您的描述,您应该可以通过调用GetOrders 方法并模拟外部服务来测试Login 方法的所有相关功能。

所以你可能会有一些这样的测试:

  • TestGetOrdersThrowsWhenExternalLoginFailsWithException
  • TestGetOrdersThrowsWhenExternalLoginFailsWithError
  • TestGetOrdersThrowsWhenExternalProviderHasNoOrders
  • TestGetOrdersReturnsOrdersFromExternalProviderWhenPresent

您的测试应该只是您班级的另一个客户。因此,他们只关心类的公共接口。从这个角度来看,您是否将登录功能放入 MyAPIService 中的单独私有方法中,或者是否将所有登录代码直接放入 GetOrders 方法中都无关紧要。任何调用公共GetOrders 方法的测试都应该以同样的方式工作。

重点是测试您的类,因为它们将被您的生产代码的其余部分使用。如果您开始公开所有方法以便您可以单独测试它们,那么您最终倾向于将您的测试与您的代码紧密耦合(使得任何级别的重构都比需要的更痛苦),或者重复测试( GetOrders 不能返回任何 Orders 除非外部登录成功,因此测试您的 Login 方法调用外部登录是多余的),或者您进入模拟您正在测试的类的阴暗世界(这可以通过一些模拟框架来完成)。当其他人使用您的类时,在您的类上拥有比所需更多的公共方法也会让他们感到困惑(嗯……看起来我需要调用Login,然后我可以调用GetOrders)。

【讨论】:

    猜你喜欢
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 2019-12-29
    • 2016-11-02
    相关资源
    最近更新 更多