【问题标题】:Spring MockMVC, Spring security and MockitoSpring MockMVC、Spring 安全性和 Mockito
【发布时间】:2016-02-05 02:30:04
【问题描述】:

我想测试一个使用Spring security 保护的Spring Boot Rest 控制器,并在其中使用模拟。我尝试过使用 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 security 抱怨配置:

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.

我没有其他想法来制作安全和嘲笑。任何想法?还是我应该采取其他方式?

谢谢。

【问题讨论】:

  • 您使用的是 Spring Security 4+ 版本吗?
  • 我一直在使用 Spring-boot 1.2.7.RELEASE,并且我已经覆盖了默认的 Spring 安全性以使用 4.0.2
  • @Remi 你解决过这个问题吗?
  • @hvgotcodes 还没有,但我没有放弃成功的一天。如果我有时间找到一个想法,我会稍后再做。

标签: spring-mvc spring-security mocking


【解决方案1】:

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

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

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

【讨论】:

  • 如果我错了请告诉我,但是使用standaloneSetup 是对控制器进行充分控制以便能够在其中注入 Mocks 的唯一方法。还是有别的办法?
  • 您可以创建一个为您的服务提供模拟的测试配置。然后排除具有实际服务的配置。或者,您可以使用这两种配置并在服务的模拟版本上标记@Primary。要设置期望并验证您可以@Autowire 中的模拟服务。
  • 在我的情况下 springSecurityFilterChain 仍然为空......我还需要在这里提供什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-22
  • 2015-03-05
  • 2013-09-01
  • 2015-12-02
  • 1970-01-01
相关资源
最近更新 更多