我如何测试父方法?
How do I test parent methods?
假设我有一个如下所示的界面:
interface IMyAPIService
{
List<Order> GetOrders();
}
以及实现它的class:
class MyAPIService : IMyAPIService
{
public List<Order> GetOrders() {}
public bool Login() {}
}
登录调用外部服务。我可以模拟外部服务,因此测试登录没有问题。
但 GetOrders 必须先调用登录,然后才能执行需要执行的操作。
我希望能够测试如果登录错误,GetOrders 也会 return 出错,但我无法模拟登录,因为它是同一个 class 的成员。我可以模拟登录调用的外部服务并确保它 return 错误然后我知道登录将 return 错误但我不确定这是否是正确的方法。
我应该只测试 IMyAPIService 中的接口方法而不是 MyAPIService 中的所有 public 方法吗?那么如何测试登录?
为 class 的 public 接口编写测试。如果您的程序中没有代码会调用 MyAPIService
上的 Login
方法,那么它就没有理由出现在 class 的 public 接口上。
根据您的描述,您应该可以通过调用 GetOrders
方法并模拟外部服务来测试 Login
方法的所有相关功能。
所以你可能会有这样的测试:
- TestGetOrdersThrowsWhenExternalLoginFailsWithException
- TestGetOrdersThrowsWhenExternalLoginFailsWithError
- TestGetOrdersThrowsWhenExternalProviderHasNoOrders
- TestGetOrdersReturnsOrdersFromExternalProviderWhenPresent
您的测试应该只是您 class 的另一个客户端。因此,他们只关心 class 的 public 接口。从这个角度来看,无论您是将登录功能放入 MyAPIService
中的单独私有方法中,还是将所有登录代码直接放入 GetOrders
方法中,都没有关系。任何调用 public GetOrders
方法的测试都应该以相同的方式工作。
重点是测试您的 classes,因为它们将被您的其余生产代码使用。如果你开始制作你所有的方法 public 以便你可以单独测试它们,那么你最终往往会将你的测试与你的代码紧密耦合(使得任何级别的重构都比它需要的更痛苦),或重复测试(GetOrders
不能 return 任何 Orders
除非外部登录成功,所以测试你的 Login
方法调用外部登录是多余的),或者你进入模拟你正在测试的 class 的阴暗世界(这可以通过一些模拟框架来完成)。在你的 class 上拥有比需要更多的 public 方法也会让其他人在使用你的 class 时感到困惑(嗯......看起来我需要调用 Login
,然后我可以打电话给GetOrders
).
假设我有一个如下所示的界面:
interface IMyAPIService
{
List<Order> GetOrders();
}
以及实现它的class:
class MyAPIService : IMyAPIService
{
public List<Order> GetOrders() {}
public bool Login() {}
}
登录调用外部服务。我可以模拟外部服务,因此测试登录没有问题。
但 GetOrders 必须先调用登录,然后才能执行需要执行的操作。
我希望能够测试如果登录错误,GetOrders 也会 return 出错,但我无法模拟登录,因为它是同一个 class 的成员。我可以模拟登录调用的外部服务并确保它 return 错误然后我知道登录将 return 错误但我不确定这是否是正确的方法。
我应该只测试 IMyAPIService 中的接口方法而不是 MyAPIService 中的所有 public 方法吗?那么如何测试登录?
为 class 的 public 接口编写测试。如果您的程序中没有代码会调用 MyAPIService
上的 Login
方法,那么它就没有理由出现在 class 的 public 接口上。
根据您的描述,您应该可以通过调用 GetOrders
方法并模拟外部服务来测试 Login
方法的所有相关功能。
所以你可能会有这样的测试:
- TestGetOrdersThrowsWhenExternalLoginFailsWithException
- TestGetOrdersThrowsWhenExternalLoginFailsWithError
- TestGetOrdersThrowsWhenExternalProviderHasNoOrders
- TestGetOrdersReturnsOrdersFromExternalProviderWhenPresent
您的测试应该只是您 class 的另一个客户端。因此,他们只关心 class 的 public 接口。从这个角度来看,无论您是将登录功能放入 MyAPIService
中的单独私有方法中,还是将所有登录代码直接放入 GetOrders
方法中,都没有关系。任何调用 public GetOrders
方法的测试都应该以相同的方式工作。
重点是测试您的 classes,因为它们将被您的其余生产代码使用。如果你开始制作你所有的方法 public 以便你可以单独测试它们,那么你最终往往会将你的测试与你的代码紧密耦合(使得任何级别的重构都比它需要的更痛苦),或重复测试(GetOrders
不能 return 任何 Orders
除非外部登录成功,所以测试你的 Login
方法调用外部登录是多余的),或者你进入模拟你正在测试的 class 的阴暗世界(这可以通过一些模拟框架来完成)。在你的 class 上拥有比需要更多的 public 方法也会让其他人在使用你的 class 时感到困惑(嗯......看起来我需要调用 Login
,然后我可以打电话给GetOrders
).