2012-04-17 3 views
1

В модульных тестах было много вопросов относительно управления областями запросов, и главным образом ответ заключается в том, что не проверяйте управление областью как свою задачу Spring Framework, и она должна заботиться о том, чтобы она работала правильно. Таким образом, например, совет может заменить область запроса областью потока или прототипа в файле конфигурации XML.Контроль области видимости объекта в тестах модулей

Для большинства тестов достаточно, нет никаких претензий в отношении незарегистрированного объема запроса и тестов. Но у меня есть один случай, когда этого недостаточно.

Рассмотрим следующий случай:

@Component 
@Scope("request") 
public class MyService { 

    @Autowired 
    private MyComponent component; 

    public void doSomething(String param) { 
     component.doTheThing(param); 
    } 
} 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:my-scope-tweaks.xml"}) 
public class MyServiceTest { 

    @Autowired 
    private MyService service; 

    @Autowired 
    private MyComponent component; 

    @Test 
    public void test1() { 
     service.doSomething("aaa"); 

     assertEquals("AAA", component.getTheThing()); 
    } 

    @Test 
    public void test1() { 
     service.doSomething("bbb"); 

     assertEquals("BBB", component.getTheThing()); 
    } 

} 

Я хочу проверить MyService, который является запрос-Scoped. MyComponent - это область запроса.

Вариант А

Если я заменяю объем запроса с SimpleThreadScope, то в обоих тестах я получил бы тот же экземпляр MyService и MyComponent, так, например, test2() может получить плохие результаты из MyComponent как он мог внутренне содержать какой-то внутренний «мусор» от предыдущего test1()

Вариант B

Если я заменяю область запроса с областью прототипа - я хотел бы получить тот случай, когда мои методы испытаний receivin g различных экземпляров MyComponent как MyService - так что я не могу выполнять никаких утверждений на них.

Так что мне понадобится только область запросов, связанных с методом тестирования, где все бобы с запросом остаются только во время метода test1(), а затем уничтожаются, поэтому в течение следующих test2() они будут вновь созданы снова.

Возможно ли это?

ответ

0

Возможно, это не то, что вы ищете, но почему вы используете Spring для управления вашими тестовыми классами в первую очередь? Мне кажется, что это слишком тяжело. Для модульного тестирования вам не нужен контейнер DI. Просто высмеивайте зависимости и сосредоточьтесь на инкапсулированных функциях компонента или службы, которую вы тестируете.

Вы не сможете этого сделать, используя полевую инъекцию. Вам нужно будет преобразовать в конструктор или метод инъекции.

+0

Его тип интеграционного теста, который я делаю в данный момент.Для небольших модульных тестов я не использую DI, но в этом случае - намного больше и много инъекций (пример упрощается, чтобы объяснить лучше) - так что было бы излишним повторить все вручную, что обычно делает весна ... – Laimoncijus

+1

I посмотри, что ты сейчас говоришь. Тем не менее, по-прежнему существует запах кода с тем, как вы вводите «Компонент». Вы хотите, чтобы Spring снова вводил его снова для каждого теста, но этого не произойдет, даже с областью прототипа (вариант B). Весна только собирается ввести объект один раз. Чтобы делать то, что вы хотите, вам придется на самом деле иметь копию «Context» и «_ask_ Spring» каждый раз для нужного вам объекта. Кроме того, вы можете получить доступ к состоянию, которое вам нужно утверждать с помощью объекта 'MyService', вместо необходимости отдельной копии« Компонента »? –

+0

Вы правы, доступ к 'MyComponent' через' MyService' с прототипом мне подойдет, поэтому мне не нужно дополнительно к '@ Autowire' в моем тестовом классе. – Laimoncijus

0

Можно получить новый контекст для каждого метода в вашем модульном тесте, аннотируя метод с помощью @DirtiesContext. Это позволяет вам манипулировать компонентами в контексте приложения для одного модульного теста и не влиять на других.

Documentation

Ваш пример с аннотацией @DirtiesContext:

@Component 
@Scope("request") 
public class MyService { 

    @Autowired 
    private MyComponent component; 

    public void doSomething(String param) { 
     component.doTheThing(param); 
    } 
} 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:my-scope-tweaks.xml"}) 
public class MyServiceTest { 

    @Autowired 
    private MyService service; 

    @Autowired 
    private MyComponent component; 

    @Test 
    @DirtiesContext 
    public void test1() { 
     service.doSomething("aaa"); 

     assertEquals("AAA", component.getTheThing()); 
    } 

    @Test 
    @DirtiesContext 
    public void test2() { 
     service.doSomething("bbb"); 

     assertEquals("BBB", component.getTheThing()); 
    } 

} 

Если все методы испытаний в вашем классе требуют нового контекста вы также можете просто аннотировать класс следующим образом:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:my-scope-tweaks.xml"}) 
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) 
public class MyServiceTest { 
    //Tests Here... 
} 
Смежные вопросы