Spring MockMVC,Spring security和Mockito

时间:2015-11-04 14:33:42

标签: spring-mvc spring-security mocking

我想测试Spring Boot Rest控制器,它使用Spring security进行保护,并在其中使用模拟。我曾尝试使用Mockito,但我认为任何嘲弄工具都可以解决问题。

要在我的测试中启用Spring安全性,我首先做了如下:

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

直到那里,它运作良好。

在这一步之后,我希望添加模拟来单独测试我的安全控制器。

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

但在这种情况下,我有另一个问题。 Spring安全性抱怨配置:

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.

我没有其他想法来做出安全和嘲笑。任何的想法?或者我应该采取其他方式吗?

感谢。

1 个答案:

答案 0 :(得分:11)

默认情况下,集成会查找名为“springSecurityFilterChain”的bean。在提供的示例中,正在使用独立设置,这意味着MockMvc将不会知道测试中提供的WebApplicationContext,因此无法查找“springSecurityFilterChain”bean。 / p>

解决此问题的最简单方法是使用以下内容:

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