Я бы дал тест-методу класса Bot параметр, который принимает функцию String с одним параметром, обратный вызов и обратный вызов через этот метод.
Но на самом деле любой обратный вызов подойдет, но ссылки на функции Java 8будет работать идеально.
например,
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import javax.swing.*;
public class FooJPanel extends JPanel {
private JButton btn = new JButton("Button");
private JTextArea textAreaMain = new JTextArea(20, 20);
public FooJPanel() {
textAreaMain.setFocusable(false);
add(new JScrollPane(textAreaMain));
add(btn);
btn.addActionListener(e -> {
final Bot bot = new Bot();
SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
bot.run(this::publish); // thanks Vince Emigh
return null;
}
@Override
public void process(List<String> chunks) {
for (String s : chunks) {
textAreaMain.append(s + "\n");
}
}
};
worker.execute();
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FooJPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
class Bot {
public void run(Consumer<String> c) {
for (int i = 0; i < 10; i++) {
c.accept("String #" + i);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
}
}
}
Но любая конструкция обратного вызова или слушателя будет работать, например, PropertyChangeListener.Пока вы поддерживаете низкий уровень сцепления и высокий уровень сцепления, у вас все получится.