С помощью JUnit
5.5 мы получаем возможность определить InvocationInterceptors , чтобы получить больший контроль над действиями, выполняемыми на различных этапах жизненного цикла теста.
Поэтому я создал этот перехватчик для заменыJUnit 4 подходит с правилами для запуска потоков пользовательского интерфейса и выполнения в них метода теста:
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
import javax.swing.*;
import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
public class JavaFxInterceptor implements InvocationInterceptor {
@Override
public void interceptBeforeAllMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
long timeMillis = System.currentTimeMillis();
final CountDownLatch latch = new CountDownLatch(1);
SwingUtilities.invokeLater(() -> {
// initializes JavaFX environment
new JFXPanel();
latch.countDown();
});
System.out.println("javafx initialising...");
latch.await();
System.out.println("javafx is initialised in " + (System.currentTimeMillis() - timeMillis) + "ms");
}
@Override
public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
AtomicReference<Throwable> throwable = new AtomicReference<>();
Platform.runLater(() -> {
try {
invocation.proceed();
}
catch (Throwable t) {
throwable.set(t);
}
});
Throwable t = throwable.get();
if (t != null) {
throw t;
}
}
}
, а затем адаптирует существующий тест для запуска с этой новой функцией:
import ch.sahits.game.graphic.image.impl.SelectiveCachableXMLImageLoader;
import ch.sahits.game.openpatrician.model.IHumanPlayer;
import ch.sahits.game.openpatrician.model.player.EPlayerColor;
import ch.sahits.game.openpatrician.model.ship.EShipType;
import ch.sahits.game.openpatrician.model.ship.IShip;
import ch.sahits.game.openpatrician.testutilities.JavaFxInterceptor;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Point2D;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
@ExtendWith(JavaFxInterceptor.class)
public class ShipIconTest {
@BeforeAll
private static void initJAvaFX() {
}
@Test
public void shouldUpdateShipPositionInitialisation() {
// Given
IShip vessel = mock(IShip.class);
IHumanPlayer player = mock(IHumanPlayer.class);
SelectiveCachableXMLImageLoader imageLoader = new SelectiveCachableXMLImageLoader("imageDefinitions.xml");
Jaxb2Marshaller bean = new Jaxb2Marshaller();
bean.setContextPath("ch.sahits.game.graphic.data.image");
try {
Field f = imageLoader.getClass().getDeclaredField("unmarshaller");
f.setAccessible(true);
f.set(imageLoader, bean);
Method m = imageLoader.getClass().getDeclaredMethod("loadImageFile");
m.setAccessible(true);
m.invoke(imageLoader);
} catch (NoSuchFieldException|IllegalAccessException|NoSuchMethodException|InvocationTargetException e) {
e.printStackTrace();
}
given(vessel.getOwner()).willReturn(player);
given(vessel.getLocation()).willReturn(new Point2D(47, 11));
given(vessel.pirateFlagProperty()).willReturn(new SimpleBooleanProperty(false));
given(vessel.getShipType()).willReturn(EShipType.COG);
given(player.getColor()).willReturn(EPlayerColor.BURGUNDY);
// When
ShipIcon shipIcon = new ShipIcon(vessel, player, imageLoader);
// Then
assertEquals(47 - 32, shipIcon.getLayoutX(), 0.001);
assertEquals(11 -32, shipIcon.getLayoutY(), 0.001);
}
}
Я думаюфактическая реализация метода теста в этом случае не имеет значения, так как он не выполняется, и я получаю следующие выходные данные:
javafx initialising...
javafx is initialised in 427ms
Test ignored.
org.junit.platform.commons.JUnitException: Chain of InvocationInterceptors never called invocation: org.junit.jupiter.engine.extension.TimeoutExtension, ch.sahits.game.openpatrician.testutilities.JavaFxInterceptor
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.fail(InvocationInterceptorChain.java:137)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.verifyInvokedAtLeastOnce(InvocationInterceptorChain.java:130)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:44)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllMethods$8(ClassBasedTestDescriptor.java:371)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllMethods(ClassBasedTestDescriptor.java:369)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:193)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:77)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:132)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Поток пользовательского интерфейса JavaFX
инициализируется, но фактический тест игнорируетсяи я не могу сделать голову или хвосты исключения. Отладка показывает, что interceptTestMethod
никогда не вводится. Я предполагаю, что я поступаю неправильно, но как правильно?