2015-07-23 4 views
5

У меня есть компонент, похожий на этот:Testing весна фасоль с поста построить

@Service 
public class A { 
    @Autowired 
    private B b;  
    @PostConstruct 
    public void setup() { 
     b.call(param); 
    } 
} 

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = { Application.class, Config.class }) 
@WebIntegrationTest(randomPort = true) 
public class Test { 
    @Autowired 
    B B; 
    @Before 
    public void setUp() throws Exception { 
     when(b.call(any())).thenReturn("smth"); 
    } 
    @Test 
    public void test() throws Exception { 
     // test... 
    } 
} 

Проблема заключается в том, что PostConstruct вызывается перед setUp при выполнении теста.

+0

@hzp z Класс A имеет другую логику, которая вызывается в последнем тесте. И отвечая на ваш вопрос, я бы хотел проверить логику класса A. – Andy

ответ

8

Если вы хотите написать блок тест A, тогда не используйте Spring. Вместо этого создайте экземпляр A и пропустите заглушку/макет B (либо с помощью впрыска конструктора, либо ReflectionTestUtils, чтобы установить личное поле).

Например:

@Service 
public class A { 

    private final B b;  

    @Autowired 
    public A(B b) { 
     this.b = b; 
    } 

    @PostConstruct 
    public void setup() { 
     b.call(param); 
    } 
} 

-

public class Test { 

    @Test 
    public void test() throws Exception { 
     B b = mock(b); 
     A a = new A(b); 
     // write some tests for A 
    } 

} 

Если вы должны использовать Spring, потому что вы хотите написать интеграции тест, использовать другой контекст приложения, где вы заменить B с заглушкой/макетом.

Например, если предположить B конкретизируется в Production классе, как это:

@Configuration 
public class Production { 

    @Bean 
    public B b() { 
     return new B(); 
    } 

} 

Написать другой @Configuration класс для ваших тестов:

@Configuration 
public class Tests { 

    @Bean 
    public B b() { 
     // using Mockito is just an example 
     B b = Mockito.mock(B.class); 
     Mockito.when(b).thenReturn("smth"); 
     return b; 
    } 

} 

ссылки на него в тесте с @SpringApplicationConfiguration аннотацию:

@SpringApplicationConfiguration(classes = { Application.class, Tests.class }) 
+0

Спасибо! Да, это почти правильно. Кроме '@Configuration Тесты общественных класса { @Bean общественных B B() { \t B B = Mockito.mock (B.class); \t Mockito.when (b). ThenReturn ("smth"); return b; } } ' – Andy

+0

Эта первая часть решения позволяет избежать реальной проблемы, убив« интеграционную »часть теста. Вторая часть намного лучше – cahen

+2

@cahen Вот почему я начал с «Если вы хотите написать ** unit ** test». По моему опыту, люди часто склонны писать интеграционный тест, когда они действительно хотят провести единичный тест. – hzpz

Смежные вопросы