2015-11-04 22 views
7

Ich möchte einen Spring Boot Rest Controller, der mit Spring security gesichert ist, testen und Mocks darin verwenden. Ich habe es mit Mockito versucht, aber ich denke, jedes Spottwerkzeug sollte den Trick machen.Spring MockMVC, Spring security und Mockito

Frühlings- und Sicherheit in meinen Tests zu ermöglichen, habe ich zuerst wie folgt:

@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())); 
    } 
} 

Bis da, es funktioniert gut.

Nach diesem Schritt wollte ich Mocks hinzufügen, um meinen gesicherten Controller isoliert zu testen.

@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())); 
    } 
} 

Leider ist der verspottete Dienst in der Steuerung nicht gespritzt, so gibt es nichts, das MockMVC und die Mocks beziehen, so dass die Mocks sind nicht in der Steuerung injiziert. So

Ich habe versucht, die Konfiguration des MockMVC ändern, wie folgt:

@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())); 
    } 
} 

Aber in diesem Fall habe ich ein anderes Problem. Frühlingssicherheit beschwert sich über die Konfiguration:

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. 

Ich habe keine andere Idee, Sicherheit und Mocking zu machen. Irgendeine Idee? Oder sollte ich einen anderen Weg gehen?

Danke.

+0

verwenden Sie Spring Security 4+ Version? – Ritesh

+0

Ich benutze Spring-Boot 1.2.7.RELEASE und ich habe Standard-Spring-Sicherheit überschrieben, um 4.0.2 –

+0

@Remi zu verwenden Haben Sie das jemals gelöst? – hvgotcodes

Antwort

9

Standardmäßig sucht die Integration nach einer Bean mit dem Namen "springSecurityFilterChain". In dem Beispiel, das bereitgestellt wurde, wird ein Standalone-Setup verwendet, was bedeutet, dass MockMvc das WebApplicationContext, das in dem Test bereitgestellt wird, nicht erkennt und daher die Bean "springSecurityFilterChain" nicht nachschlagen kann.

Der einfachste Weg, dies zu lösen ist, so etwas zu verwenden:

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

Wenn Sie wirklich eine standaloneSetup verwenden möchten (nicht wirklich sinnvoll ist, da Sie bereits eine WebApplicationContext haben), können Sie verwenden, können explizit die springSecurityFilterChain bieten:

@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

Sagen Sie mir, wenn ich falsch liege, aber die Verwendung von 'StandaloneSetup' ist die einzige Möglichkeit, eine ausreichende Kontrolle über den Controller zu haben, um Mocks hinein zu injizieren. Oder gibt es einen anderen Weg? –

+0

Sie können eine Testkonfiguration erstellen, die Mocks für Ihre Dienste bereitstellt. Schließen Sie dann die Konfiguration mit den eigentlichen Diensten aus. Alternativ können Sie beide Konfigurationen verwenden und '@ Primary' in der Mock-Version der Dienste markieren. Um die Erwartungen festzulegen und zu verifizieren, können Sie die Mock-Dienste in "Autowire" versetzen. –