5

我创建了一个扩展第 3 方抽象类的新类。新类调用抽象类中的方法。我遇到的问题是在尝试编写单元测试时,我不确定如何编写测试,因为我不知道 3rd 方类所需的确切细节。

下面的 AbstractDecoratorMapper 是 SiteMesh 特定的类,我必须扩展它才能使 SiteMesh 正常工作。据我从文档中可以看出,我不能使用组合。

public final class PartnerDecoratorMapper extends AbstractDecoratorMapper {

    @Override
    public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException {
        super.init(config, properties, parent);
    }

    @Override
    public Decorator getDecorator(HttpServletRequest request, Page page) {
        if (super.getDecorator(request, page).getName().equalsIgnoreCase("default")) {
            return getNamedDecorator(request, "externalPartnerDefault");
        }
        return super.getDecorator(request, page);
    }
}

如果这个工具可以提供任何帮助,我会使用 JMock。

4

4 回答 4

4

您不需要了解 3rd 方库的详细信息……您只需要模拟它们返回您期望从它们那里得到的东西。

在您继承它的情况下,您可以设置该类,因为它将在生产中使用并调用应该在常规使用中调用的方法。您需要检查的只是结果是否符合您的预期。(您不需要确切知道第 3 方课程在测试中的工作方式)。

为了检查您实现的所有代码是否已执行,您可以使用插件来检查覆盖率,例如 eclemma - http://www.eclemma.org/

于 2012-06-11T10:00:31.780 回答
3

使用 JMock,据我所知,您无法模拟对被测类的超类的调用。

这个相关问题的答案可能很有用,但主要的答案是切换到支持这个的模拟框架(建议使用JMockit)。

于 2012-06-11T11:20:01.477 回答
2

您可能会问两件事。我会尽力回答这两个问题。

可能的问题 1) 我如何测试我的附加功能?

可能的问题2)我如何测试组合功能是否合适?

让我从问题 1 开始。

我建议一个简单的果皮。这里有一个技术视频:http ://www.youtube.com/watch?v=p0tILwRZH5Q (视频是 c# 但在 java 中基本相同)

这意味着您之后将拥有以下代码

@Override
public Decorator getDecorator(HttpServletRequest request, Page page) {
    Decorator d = super.getDecorator(request, page);
    return getResolvedDecorator(d, d.getName(), request);

}
public Decorator getResolvedDecorator(Decorator current, String name, HttpServletRequest request) {
    if (name.equalsIgnoreCase("default")) {
        return getNamedDecorator(request, "externalPartnerDefault");
    }
    return current;
}

现在你可以用这样的电话来测试它

assertEquals(expected, new PartnerDecoratorMapper().getResolvedDecorator(null, "default", MockHttpServletRequest);

我建议也可能从 HttpServletRequest 中删除数据,以使测试和意图更清晰。

注意:这具有额外的性能优势,即对 super.getDecorator() 的调用只发生一次,因为结果被缓存了。

附加说明:还值得注意的是,init() 的覆盖是不需要的,实际上并没有做任何事情。

问题 2:这是一个更难的问题,因为您没有说明所需的行为是什么。我假设这是一种工厂模式,所以很可能它会以某种方式工作

| http请求质量1 | 页面质量 1| 预期装饰者 | | /mypath/mypage | 状态 = 富 | 我的装饰器 |

(我不知道上面的图表应该包含什么或看起来像什么)一旦你有这种行为,那么测试以确保它会相当简单。

快乐测试,卢埃林

于 2012-06-11T11:58:58.773 回答
1

因为我不知道第 3 方课程需要的确切细节

任何类型的测试都会比较某事实际做了什么和它该做什么。在您知道应该做什么之前,您无法进行测试:“第 3 部分课程需要什么”。

如果你不知道基类需要什么,你怎么能做出任何合理的尝试来编写你的派生类呢?您要扩展的类的 API 文档是怎么说的?

问题可能是没有这样的 API 文档,还是没有提供信息?可能是,尽管该类不是final,但它并不是真正打算用作基类。其中任何一个都表明 API 设计不佳,建议您不要费心使用它

还是您不知道确切细节的关键困难?这可能是您的方法中的一个缺陷:通常您不能也不能对确切的细节做出假设。您的代码应符合文档化 API,并且您不应假设文档化 API 中未说明的任何内容。这可能意味着您无法知道何时调用模板方法或将传递给它们的值是什么。如果基类通过传递声明为实现类interface或非final类的对象(即指定其类型但未指定其)与您的模板方法进行通信,则您无法知道这些对象将具有什么类。

于 2012-06-11T12:24:13.787 回答