繁体   English   中英

Java`final`类和嘲弄

[英]Java `final` class and mocking

我正在开发一种编程游戏,玩家可以访问抽象类并扩展它以控制机器人的行为。 因为它是一个编程游戏,我试图保护我的游戏基础设施,以便玩家不会混淆游戏,而不仅仅是我给他们的课程; 为此,我将我的大部分课程定为final但现在我无法在单元测试中模拟它们(mockito + testNG)。

所以我想知道,我该如何解决这个问题呢? 有没有办法让这些类非最终用于测试,然后以某种方式在构建周期的后期自动“ final化”它们(我正在使用maven,以防它与答案相关)。 我不想添加另一个外部库或更改我的模拟库。
如果不可能,那么第二个问题让一个班级final真正安全吗? 我看到一些库可以从字节码中删除final分类器,这让我觉得如果可以从已经编译的类中删除它,那么final也许是无用的

首先,你不能通过宣布“最终”来阻止人们搞乱你的游戏。 有反射技巧和整个代码生成库,只是稍微不方便通过它。

所以,输掉决赛,然后你可以使用jmock或任何你喜欢的库来制作模拟。

您最终可以尝试应用自动重构工具,例如Jackpot 3RefactoringNG 我从未对它们进行过测试,但如果采用重构的方式,它们就能胜任你想做的事情。

另一种方法是使用Powermock,允许模拟决赛和静电(甚至很难我不喜欢嘲弄静态,因为它表明你的设计有问题)。

您始终可以使用委派而不是继承。

public interface Foo {
    // ...
}

public final class FooImpl implements Foo {
    // ...
}

public class MockFooImpl implements Foo {
    private FooImpl delegate;
    // ...
}

但是,在API中使用抽象类是个坏主意。 界面会更好。

IMO,类被标记为final以使其对象不可变。 如果要控制类的行为,请将类中的方法标记为私有,以便不能覆盖它们。 如果你保护它们,那么有人可以扩展你的类,覆盖这些受保护的方法,并将扩展类的实例传递给你希望你的类对象作为参数的API,从而引发修改后的行为。 因此,您可以将不希望公开的方法标记为私有。

根据使用这些类的客户端可以覆盖自定义行为的受保护/公共方法,只保留扩展点。

使大多数类final是最好的做法,因为它们通常不是为子类化扩展而设计的。 所有关于API设计的书籍我都知道建议这样做(“Effective Java”,“Practical API Design”,“API Design for C ++”)。 这有利于几个原因,包括API设计者的意图表达,API的安全演变以及防止死代码(例如,一个好的IDE将检测何时final方法不使用其中一个参数,或者永远不会抛出throws子句中列出的已检查异常 - 这对于非最终方法是不可能的。

至于模拟所说的类,你只需要使用一个适当的模拟工具,比如JMockit (我开发的正是因为我想编写单元测试而不牺牲某些OO / API设计实践)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM