Новый Бин каждый @Test - PullRequest
0 голосов
/ 07 ноября 2018

Я создаю среду тестирования Appium для гибридного приложения, используя Spring Boot 2.0.1, и у меня возникают проблемы с использованием Spring TestExecutionListeners.

Цель: Инициализировать новый экземпляр AppiumDriver<WebElement> для каждого теста, помеченного @Test JUnit, и завершать эти экземпляры драйвера, используя AppiumDriver quit() после каждого теста.

Структура моей платформы: Я создал пользовательскую область с именем TestScope

public class TestScope implements Scope {

    private Map<String, Object> scopedObjects = Collections.synchronizedMap(new HashMap<String, Object>());
    private Map<String, Runnable> destructionCallbacks = Collections.synchronizedMap(new HashMap<String, Runnable>());

    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        if (!this.scopedObjects.containsKey(name)) {
            this.scopedObjects.put(name, objectFactory.getObject());
        }
        return this.scopedObjects.get(name);
    }

    @Override
    public String getConversationId() {
        return null;
    }

    @Override
    public void registerDestructionCallback(String name, Runnable callback) {
        this.destructionCallbacks.put(name, callback);
    }

    @Override
    public Object remove(String name) {
        this.destructionCallbacks.remove(name);
        return this.scopedObjects.remove(name);
    }

    public void reset() {
        this.scopedObjects.clear();
    }

    @Override
    public Object resolveContextualObject(String key) {
        return null;
    }
}

Я регистрирую TestScope в файле конфигурации моего приложения (Application.java), создав его единичный экземпляр, а также зарегистрировав мой компонент AppiumDriver<WebElement> и предоставив ему только что созданную область действия "test":

@SpringBootApplication
@PropertySource("classpath:application.properties")
public class Application implements EnvironmentAware {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CustomScopeConfigurer customScopeConfigurer() {
        CustomScopeConfigurer scopeConfigurer = new CustomScopeConfigurer();
        Map<String, Object> scopes = new HashMap<>();
        scopes.put("test", this.testScope());
        scopeConfigurer.setScopes(scopes);
        return scopeConfigurer;
    }

    @Bean
    @Scope("test")
    public AppiumDriver<WebElement> driver() {
        DesiredCapabilities caps = new DesiredCapabilities();
        caps.setCapability(MobileCapabilityType.PLATFORM_NAME, this.env.getProperty("platformName"));
        caps.setCapability(MobileCapabilityType.PLATFORM_VERSION, this.env.getProperty("platformVersion"));
        caps.setCapability(MobileCapabilityType.DEVICE_NAME, this.env.getProperty("deviceName"));
        caps.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT,
                Integer.parseInt(this.env.getProperty("newCommandTimeout")));
        caps.setCapability(MobileCapabilityType.AUTO_WEBVIEW, true);
        // Android Capabilities
        if (this.env.getProperty("platformName").equals("Android")) {
            caps.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, this.env.getProperty("androidAppPackage"));
            caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, this.env.getProperty("androidAppActivity"));
        }
        try {
            return new AppiumDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), caps);
        } catch (Exception e) {
            throw new BeanCreationException("driver", "Failed to create Driver", e);
        }
    }

    @Bean
    public TestScope testScope() {
        return new TestScope();
    }
}

После этого я создаю AbstractTestBase с правильной аннотацией конфигурации. Мой тест будет выполнен следующим образом: они должны расширять с AbstractTestBase, чтобы они наследовали конфигурацию, и поэтому их тесты создают новые AppriumDriver instaces для каждого теста:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Application.class)
@TestExecutionListeners({ AppiumTestExecutionListener.class, DependencyInjectionTestExecutionListener.class })
public abstract class AbstractTestBase {

  @Autowired protected PageObject1 pageObj1;
  @Autowired protected PageObject2 pageObj2;
}

Наконец, в AppiumTestExecutionListener, который я установил в AbstractTestBase, я написал логику для очистки моего экземпляра TestScope перед каждым тестом и выхода из экземпляра AppiumDriver после каждого теста, чтобы при beforeTestMethod() вызывается во 2-м тесте, очищает TestScope, и Spring вынужден создавать новый экземпляр драйвера, но по какой-то причине 1-й тест работает нормально, а второй завершается неудачно, сообщая мне, что сеанс завершен.

public class AppiumTestExecutionListener extends AbstractTestExecutionListener {

    @Override
    public void afterTestMethod(TestContext testContext) throws Exception {
        testContext.getApplicationContext().getBean(AppiumDriver.class).quit();
    }

    @Override
    public void beforeTestMethod(TestContext testContext) throws Exception {
        testContext.getApplicationContext().getBean(TestScope.class).reset();
    }
}

Не уверен, что так происходит, но кажется, что когда я @Autowire мой драйвер в моих объектах страницы и 2-й тест запущен, каким-то образом экземпляр драйвера никогда не вводится повторно, чтобы они использовали новый экземпляр? Как бы то ни было, я хотел бы узнать, знаете ли вы, ребята, что я что-то не так, принимая во внимание то, что я пытаюсь сделать здесь.

...