gpt4 book ai didi

java - 如何重构类以便无需反射即可测试

转载 作者:行者123 更新时间:2023-12-02 12:20:01 25 4
gpt4 key购买 nike

我有一个与此类似的类(class):

public class QueueingCommandRunner {
private Status status;
private Map<Class<CommandHandler>, CommandHandler> queuedCommands;
private RunnerClass runnerClass;
private ExternalCommandRunnerRegistry externalCommandRunnerRegistry;
private ExternalCommandRunner externalCommandRunner;

public QueueingCommandRunner(ExternalCommandRunnerRegistry externalCommandRunnerRegistry,
RunnerClass runnerClass) {

this.externalCommandRunnerRegistry = externalCommandRunnerRegistry;
this.runnerClass = runnerClass;
this.queuedCommands = new LinkedHashMap<>();
this.status = Status.DOWN;
}

public void init() {
doSomeStuff();
externalCommandRunner = externalCommandRunnerRegistry.get(runnerClass);
externalCommandRunner.runListeningCommand(ListenableStatusCommand.class,
new ListenableStatusHandler(this::changeStatus));
}

public <T extends CommandHandler> void runCommand(Class<T> command, T commandHandler) {
if (status == UP) {
externalCommandRunner.run(command, commandHandler);
} else {
queuedCommands.put(command, commandHandler);
}
}

private void changeStatus(Status status) {
this.status = status;
if (status == UP) {
Iterator<Entry<Class<CommandHandler>, CommandHandler>> commandsIterator =
queuedCommands.iterator();
while (commandsIterator.hasNext()) {
<Entry<Class<CommandHandler>, CommandHandler>> queuedCommand = commandsIterator.next();
externalCommandRunner.run(queuedCommand.getKey(), queuedCommand.getValue());
commandsIterator.remove();
}
}
}
}

我省略了诸如同步之类的内容。我的问题是,如何测试内部的排队而不使用通过反射调用私有(private)方法之类的东西?我特别想知道如何测试 changeStatus 方法,因为它不是直接从此类中的任何公共(public)方法运行。这个类的设计是否不好(从单元测试的角度来看)?

我正在使用 JMockit 进行测试...

最佳答案

正如评论中提到的 - 你测试

desired public observable behavior

因此,如果您想测试私有(private)方法,您需要将它们公开。我建议将其作为界面:

public interface SomeInterface {

changeStatus(Status status);
}

然后将实现注入(inject)到您的类中:

public final class A {

private final SomeInterface someInterface;

public A(SomeInterface someInterface) {
this.someInterface = someInterface;
}
}

然后,您可以轻松测试 SomeInterface 实现并模拟(如果您的类 A 中需要它)。

因此,我无法为您提供针对您的特定情况的整个重构过程。但是您可以遵循此准则,并且可以使用易于测试的接口(interface)封装所有私有(private)方法。正如我所看到的,您在私有(private)方法中使用类的内部细节 - 这些细节应该封装在接口(interface)实现构造函数中(通过另一个接口(interface)),并且您最终将得到小型的、内聚的可测试类。翻阅Command Pattern因为它似乎适合您的情况并尝试遵循 SOLID这也将导致可测试的代码。

我发现您的设计有几个问题:

  • init() 方法。这会导致时间耦合,因为您的类在构造后尚未准备好使用;
  • 您的 runCommand 方法根据状态执行两件事。它要么是运行命令,要么是将其放入 map (这是隐藏的副作用);
  • 您的 changeStatus 也在运行命令。

您需要解耦这些事物(运行命令、保存它们并跟踪状态)。也许将命令的状态封装在命令本身内。因此该命令将知道如何以自己的方式工作。

关于java - 如何重构类以便无需反射即可测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45855880/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com