2015-11-04 5 views
7

Я хотел бы протестировать Spring Boot Контроллер отдыха, который защищен с помощью Spring security и использовать в нем издевательства. Я пытался с Mockito, но я думаю, что любой из насмешливый инструмент должен сделать трюк.Весна MockMVC, Весна безопасности и Mockito

Чтобы включить Spring Security в моих тестах, я первым сделал следующим образом:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Main.class) 
@TestPropertySource(value="classpath:application-test.properties") 
@WebAppConfiguration 
@ContextConfiguration 
public class MyTest{ 

    protected MockMvc mockMvc; 

    @Autowired 
    private WebApplicationContext wac; 

    @Before 
    public void setUp(){ 
     mockMvc = MockMvcBuilders 
       .webAppContextSetup(wac) 
       .apply(SecurityMockMvcConfigurers.springSecurity()) 
       .build(); 
    } 

    @Test 
    public void doTheTest(){ 
     mockMvc.perform(post("/user/register") 
      .with(SecurityMockMvcRequestPostProcessors.csrf()) 
      .content(someContent())); 
    } 
} 

До тех пор, пока он работает хорошо.

После этого шага, я хотел добавить mocks для проверки моего защищенного контроллера изолированно.

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Main.class) 
@TestPropertySource(value="classpath:application-test.properties") 
@WebAppConfiguration 
@ContextConfiguration 
public class MyTest{ 

    protected MockMvc mockMvc; 

    @Mock 
    private Myservice serviceInjectedInController; 

    @InjectMocks 
    private MyController myController; 

    @Autowired 
    private WebApplicationContext wac; 

    @Before 
    public void setUp(){ 
     mockMvc = MockMvcBuilders 
       .webAppContextSetup(wac) 
       .apply(SecurityMockMvcConfigurers.springSecurity()) 
       .build(); 
    } 

    @Test 
    public void doTheTest(){ 
     mockMvc.perform(post("/user/register") 
      .with(SecurityMockMvcRequestPostProcessors.csrf()) 
      .content(someContent())); 
    } 
} 

К сожалению, издевались служба не впрыскивается в контроллере, так как нет ничего, связывающее MockMVC и Mocks, поэтому издевается не вводят в контроллер.

Так что я попытался изменить конфигурацию MockMVC следующим образом:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Main.class) 
@TestPropertySource(value="classpath:application-test.properties") 
@WebAppConfiguration 
@ContextConfiguration 
public class MyTest{ 

    protected MockMvc mockMvc; 

    @Mock 
    private Myservice serviceInjectedInController; 

    @InjectMocks 
    private MyController myController; 


    @Before 
    public void setUp(){ 
     mockMvc = MockMvcBuilders 
       .standAloneSetup(myController) 
       .apply(SecurityMockMvcConfigurers.springSecurity()) 
       .build(); 
    } 

    @Test 
    public void doTheTest(){ 
     mockMvc.perform(post("/user/register") 
      .with(SecurityMockMvcRequestPostProcessors.csrf()) 
      .content(someContent())); 
    } 
} 

Но в этом случае, у меня есть еще один вопрос. Весна безопасности жалуется на конфигурацию:

java.lang.IllegalStateException: springSecurityFilterChain cannot be null. Ensure a Bean with the name springSecurityFilterChain implementing Filter is present or inject the Filter to be used. 

У меня нет другой идеи, чтобы сделать безопасность и насмешливость. Есть идеи? Или я должен делать другой путь?

Спасибо.

+0

вы используете Spring Security 4+ версию? – Ritesh

+0

Я использую Spring-boot 1.2.7.RELEASE, и у меня есть переопределенная безопасность по умолчанию Spring для использования 4.0.2 –

+0

@Remi Вы когда-нибудь это разрешили? – hvgotcodes

ответ

9

По умолчанию интеграция ищет компонент с именем «springSecurityFilterChain». В примере, который был предоставлен, используется автономная настройка, которая означает, что MockMvc не будет знать о WebApplicationContext, предоставленном в рамках теста, и, таким образом, не сможет найти компонент «springSecurityFilterChain».

Самый простой способ решить эту проблему, чтобы использовать что-то вроде этого:

MockMvc mockMvc = MockMvcBuilders 
      // replace standaloneSetup with line below 
      .webAppContextSetup(wac) 
      .alwaysDo(print()) 
      .apply(SecurityMockMvcConfigurers.springSecurity()) 
      .build(); 

Если вы действительно хотите использовать standaloneSetup (на самом деле не имеет смысла, так как у вас уже есть WebApplicationContext), вам можно явно предоставить springSecurityFilterChain с помощью:

@Autowired 
FilterChainProxy springSecurityFilterChain; 

@Before 
public void startMocks(){ 
    controller = wac.getBean(RecipesController.class); 

    MockMvc mockMvc = MockMvcBuilders 
      .standaloneSetup(controller) 
      .alwaysDo(print()) 
      .apply(SecurityMockMvcConfigurers.springSecurity(springSecurityFilterChain)) 
      .build(); 

    MockitoAnnotations.initMocks(this); 
} 
+0

Скажите, если я ошибаюсь, но использование 'standaloneSetup' - единственный способ иметь достаточный контроль над контроллером, чтобы иметь возможность вводить Mocks внутри. Или есть другой способ? –

+0

Вы можете создать тестовую конфигурацию, которая предоставляет вам mocks для ваших услуг. Затем исключите конфигурацию, в которой есть фактические службы. Кроме того, вы можете использовать обе конфигурации и пометить '@ Primary' в макетной версии служб. Чтобы настроить ожидания и убедиться, что вы можете '@ Autowire' выполнять макетные службы. –