FEST: запуск / остановка внешней SWING-программы, которая использует System.exit() без влияния на виртуальную машину

В моих сценариях Cucumber-jvm мне нужно запускать внешнюю jar-программу перед каждым сценарием, взаимодействовать с ней с помощью библиотеки FEST на всех этапах и, наконец, завершать работу программы, чтобы очистить планшет для следующего сценария. Мне нужна конкретная внешняя программа System.exit() выйти, когда закрыто. В свою очередь, я не могу просто выйти из программы в моих тестах, так как это приведет к завершению всей виртуальной машины. Вместо этого я использую собственный SecurityManager, встроенный в FEST, чтобы переопределить System.exit() вызов. Однако я не могу заставить его работать правильно.

Код в примере 1 ниже пытается запустить внешнюю программу в Cucumber. @Before крюк и закрыть его в @After крюк. Он отлично работает только с одним сценарием, когда я бегу mvn verify, Однако при двух или более сценариях maven просто висит на строках:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running test.acceptance.CucumberRunner 

Ничего не происходит потом. Я вижу, что внешняя программа запускается и закрывается один раз, но при втором запуске она не закрывается. Когда я закрываю его вручную, maven выводит следующее:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-failsafe-
plugin:2.16:integration-test (default) on project acceptance-tests: Execution default of
goal org.apache.maven.plugins:maven-failsafe-plugin:2.16:integration-test failed: The
forked VM terminated without saying properly goodbye. VM crash or System.exit called ?

Кто-нибудь имеет представление о том, что здесь происходит? Похоже, проблема в том, что внешняя программа вообще не завершена - возможно, ошибка NoExitSecurityManagerInstaller Я использую. Тем не менее, я не знаю, как еще предотвратить вызов System.exit для завершения всей виртуальной машины. Каким-то образом я просто хочу выйти из программы, которую я запустил, не затрагивая виртуальную машину, в которой она запущена. Это не возможно?

Обновление - Решение найдено!

Поработав с кодом в течение нескольких часов, я случайно обнаружил, что Robot класс, используемый WindowFinder имеет cleanUp метод, который: "очищает любые используемые ресурсы (клавиатура, мышь, открытые окна и {@link ScreenLock} ) используется этим роботом. ". Я пытался использовать это вместо frame.close() и оказывается, это работает! Это даже не нужно обычай SecurityManager,

Проблема в том, что BasicRobot.robotWithCurrentAwtHierarchy() Вызовите замок на экране, который НЕ снимается frame.close(), Поэтому, когда следующий звонок BasicRobot.robotWithCurrentAwtHierarchy() выполняется во втором сценарии / тесте, вызов будет блокировать ожидание снятия блокировки и создание эффективной тупиковой ситуации. Решение состоит в том, чтобы вручную снять блокировку, используя robot.cleanUp (который также закрывает и удаляет любые открытые окна). Однако почему frame.close не делает этого, когда закрывается последний кадр за мной.

Пример 1

public class CucumberHooks {
    private FrameFixture frame;

    @Before
    public void setup() throws InterruptedException, IOException {
        Thread t = new Thread(new Runnable() {
            public void run() {
                File file = new File(System.getProperty("external-jar"));
                URLClassLoader cl = null;
                try {
                    cl = new URLClassLoader( new URL[]{file.toURI().toURL()} );
                }
                catch (MalformedURLException e) {}

                Class<?> clazz = null;
                try {
                    clazz = cl.loadClass("MainClass");
                }
                catch (ClassNotFoundException e) {}

                Method main = null;
                try {
                    main = clazz.getMethod("main", String[].class);
                }
                catch (NoSuchMethodException e) {}

                try {
                    main.invoke(null, new Object[]{new String[]{}});
                }
                catch (Exception e) {}
            }
        });
        t.start();

        GenericTypeMatcher<JFrame> matcher = new GenericTypeMatcher<JFrame>(JFrame.class) {
            protected boolean isMatching(JFrame frame) {
                return "External Jar Title".equals(frame.getTitle()) && frame.isShowing();
            }
        };

        frame = WindowFinder.findFrame(matcher).using(BasicRobot.robotWithCurrentAwtHierarchy());
    }

    @After
    public void shutDown() throws InterruptedException {
        NoExitSecurityManagerInstaller i = NoExitSecurityManagerInstaller.installNoExitSecurityManager();
        frame.close();
        i.uninstall();
    }
}

Пример 2

public class CucumberHooks {
    private FrameFixture frame;
    private Robot robot;

    @Before
    public void setup() throws InterruptedException, IOException {
        Thread t = new Thread(new Runnable() {
            public void run() {
                File file = new File(System.getProperty("external-jar"));
                URLClassLoader cl = null;
                try {
                    cl = new URLClassLoader( new URL[]{file.toURI().toURL()} );
                }
                catch (MalformedURLException e) {}

                Class<?> clazz = null;
                try {
                    clazz = cl.loadClass("MainClass");
                }
                catch (ClassNotFoundException e) {}

                Method main = null;
                try {
                    main = clazz.getMethod("main", String[].class);
                }
                catch (NoSuchMethodException e) {}

                try {
                    main.invoke(null, new Object[]{new String[]{}});
                }
                catch (Exception e) {}
            }
        });
        t.start();

        GenericTypeMatcher<JFrame> matcher = new GenericTypeMatcher<JFrame>(JFrame.class) {
            protected boolean isMatching(JFrame frame) {
                return "External Jar Title".equals(frame.getTitle()) && frame.isShowing();
            }
        };

        robot = BasicRobot.robotWithCurrentAwtHierarchy();
        frame = WindowFinder.findFrame(matcher).using(robot);
    }

    @After
    public void shutDown() {
        robot.cleanUp();
    }
}

1 ответ

Это всего лишь предположение: вы должны установить NoExitSecurityManagerInstaller, прежде чем начинать свою ветку. См. http://docs.codehaus.org/display/FEST/Handling+System.exit

Другие вопросы по тегам