我想实现一个责任链模式,处理“断开的链接”问题,如下所示:
public abstract class Handler{
private Handler m_successor;
public void setSuccessor(Handler successor)
{
m_successor = successor;
}
protected abstract boolean handleRequestImpl(Request request);
public final void handleRequest(Request request)
{
boolean handledByThisNode = this.handleRequestImpl(request);
if (m_successor != null && !handledByThisNode)
{
m_successor.handleRequest(request);
}
}
}
似乎是一种足够普遍的方法。但是如何用受保护的抽象方法测试呢?处理这个问题的方法似乎是:
Handler
实现实现抽象方法的仅测试子类。这似乎不利于测试维护。- 将抽象方法的可见性更改为公共,但我不需要更改 SUT 以适应测试。
- 将抽象类视为足够简单,不需要单元测试。嗯。
handleRequest
在一个或多个具体子类上为方法实施单元测试。但这似乎不是组织测试的明智方式。- 有没有办法使用模拟对象?我试过 Mockito,但似乎无法绕过受保护的可见性。
我已经阅读[ 1 ],这种测试问题意味着设计是错误的,并建议使用组合而不是继承。我现在正在尝试这个,但是这个模式的推荐实现有这个问题似乎很奇怪,但我找不到任何关于单元测试的建议。
更新:我已经用依赖反转替换了抽象类,如图所示,现在可以使用 Mockito 轻松测试。它看起来仍然像责任链......我错过了什么吗?
// Implement a concrete class instead
public class ChainLink {
// Successor as before, but with new class type
private ChainLink m_successor;
// New type, RequestHandler
private RequestHandler m_handler;
// Constructor, with RequestHandler injected
public ChainLink(RequestHandler m_handler) {
this.m_handler = m_handler;
}
// Setter as before, but with new class type
public void setSuccessor(ChainLink successor) {
m_successor = successor;
}
public final void handleRequest(Request request) {
boolean handledByThisNode = m_handler.handleRequest(request);
if (m_successor != null && !handledByThisNode) {
m_successor.handleRequest(request);
}
}
}