пикоконтейнер для singleton DI

Я пытаюсь использовать пикоконтейнер для DI, но все еще получаю экземпляр моего общего объекта несколько раз вместо того, чтобы автоматически управлять им как синглтоном. Вот пример для иллюстрации. Классы ASteps и BSteps получают экземпляр SharedObject через свои конструкторы. Я ожидал, что пикоконтейнер будет управлять им как синглтоном: экземпляр создается только один раз, согласно документам Cucumber. Вместо этого я вижу, что он создается один раз для AS-шагов и один раз для BS-шагов:

Running my.domain.CucumberRunTest
 INFO [main] (CucumberHooks.java:15) - Executing before()
 INFO [main] (SharedObject.java:11) - SharedObject - instantiated
 INFO [main] (ASteps.java:21) - Executing a_step_one()
 INFO [main] (ASteps.java:26) - Executing a_step_two()
 INFO [main] (ASteps.java:31) - Executing a_step_three()
 INFO [main] (CucumberHooks.java:20) - Executing after()
 INFO [main] (CucumberHooks.java:15) - Executing before()
 INFO [main] (SharedObject.java:11) - SharedObject - instantiated
 INFO [main] (BSteps.java:23) - Executing b_step_one()
 INFO [main] (BSteps.java:28) - Executing b_step_two()
 INFO [main] (BSteps.java:33) - Executing b_step_three()
 INFO [main] (CucumberHooks.java:20) - Executing after()

Что я делаю не так? Вот код:

package my.domain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class ASteps {

final Logger log = LoggerFactory.getLogger(getClass());
SharedObject sharedObject;

public ASteps(SharedObject sharedObject) {
this.sharedObject = sharedObject;
}

@Given("^A step one$")
public void a_step_one() {
log.info("Executing a_step_one()");
}

@When("^A step two$")
public void a_step_two() {
log.info("Executing a_step_two()");
}

@Then("^A step three$")
public void a_step_three() {
log.info("Executing a_step_three()");
}
}

************************

package my.domain;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class BSteps {

final Logger log = LoggerFactory.getLogger(getClass());
SharedObject sharedObject;

public BSteps(SharedObject sharedObject) {
this.sharedObject = sharedObject;
}

@Given("^B step one$")
public void b_step_one() {
log.info("Executing b_step_one()");
}

@When("^B step two$")
public void b_step_two() {
log.info("Executing b_step_two()");
}

@Then("^B step three$")
public void b_step_three() {
log.info("Executing b_step_three()");
}
}

************************

package my.domain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cucumber.api.java.After;
import cucumber.api.java.Before;

public class CucumberHooks {

final Logger log = LoggerFactory.getLogger(getClass());

@Before
public void before() {
log.info("Executing before()");
}

@After
public void after() {
log.info("Executing after()");

}
}

*********************

package my.domain;

import org.junit.runner.RunWith;

import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
public class CucumberRunTest {

}

**********************

package my.domain;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SharedObject {

final Logger log = LoggerFactory.getLogger(getClass());

public SharedObject() {
log.info("SharedObject - instantiated");
}
}

person Pablo    schedule 11.10.2015    source источник


Ответы (2)


Кэш пико-контейнера: сбрасывается между сценариями, когда мир удаляется в конце сценария.

Это очень важно для каждого проекта, чтобы избежать утечки состояния между сценариями и сделать их изолированными, чтобы порядок тестов не влиял на результаты.

Если вы хотите поддерживать состояние между сценарием A и сценарием B, вам нужно либо самостоятельно обрабатывать SharedObject вне пико-контейнера, либо вы можете сделать зависимость между этими двумя сценариями явной — например, с помощью Background.

person Sébastien Le Callonnec    schedule 11.10.2015
comment
Спасибо, Себастьян, это очень полезно. В этом случае я не вижу особого смысла в использовании пикоконтейнера (я могу получить тот же результат с простыми старыми локальными переменными). Я создаю среду автоматизации тестирования и хочу определить разные области для разных типов ресурсов: ресурсы с областью действия сценария (например, экземпляр WebDriver) или ресурсы области выполнения (например, конфигурация выполнения, соединения с БД и другие неизменяемые или дорогостоящие ресурсы). ). Мне все еще нужно понять весь жизненный цикл Cucumber JVM. Вы знаете какие-нибудь хорошие ресурсы для этого? Или исходный код мой лучший вариант? - person Pablo; 12.10.2015
comment
@Pablo Боюсь, я ничего не знаю - я обычно проверяю источники огурца-jvm. Однако они хорошо написаны, поэтому за ними довольно легко следовать. Проверьте CucumberScenario#run (github.com/cucumber/cucumber-jvm/blob/master/core/src/main/java/), именно здесь для сценария происходит волшебство. - person Sébastien Le Callonnec; 12.10.2015

Надеюсь, еще не поздно ответить на ваш вопрос.

На самом деле, вы можете иметь то, что хотите. Я видел, что вы также хотите иметь один экземпляр вашего браузера. Для этого вы должны использовать статические объекты. Я создал небольшой класс, чтобы избежать открытия/закрытия драйвера между каждым тестом. Он управляется пикоконтейнером. В ваших классах stepDefinition вы должны реализовать «тот же самый» конструктор.

Вот пример:

public class myStepDefinition{
    private Drivers context;
    public myStepDefinition(Drivers context){
        this.context = context;
        // whatever you want to do
    }
}

public class Drivers {
    private static boolean initialized = false;
    private static WebDriver driver;

    @Before
    public void initialize(){
        if (!initialized){
            initialized = true;
            driver = new FirefoxDriver();
            driver.manage().window().maximize();
            driver.get("http://www.myurl.url");
        }
    }

    public static WebDriver getDriver(){
        return driver;
    }
}

Имейте в виду, что вы должны возвращаться на свою страницу входа или на стартовую страницу после каждого теста (пройденного или не пройденного)

С уважением,

Николя

person Nicolas G. Duvivier    schedule 28.10.2015