如何在 MockMVC 中模拟一些 bean 而不是其他的?

Posted

技术标签:

【中文标题】如何在 MockMVC 中模拟一些 bean 而不是其他的?【英文标题】:How to mock some beans but not others in MockMVC? 【发布时间】:2020-02-21 03:31:23 【问题描述】:

我正在尝试为控制器编写单元测试。我用@MockBean 模拟了一些依赖项(例如服务类)。但是还有其他依赖项,我想让 spring 像往常一样创建 bean。这可能吗?

@RunWith(SpringRunner.class)
@WebMvcTest(JwtAuthenticationController.class)
public class JwtControllerTests 

    @MockBean
    private JwtUserDetailsService jwtUserDetailsService;

    @MockBean
    private AuthenticationManager authenticationManager;

    @ ? ? ?
    private JwtTokenUtil jwtTokenUtil

    public void auth_Success() throws Exception 
        when(
            jwtUserDetailsService.loadUserByUsername(anyString())
        ).thenReturn(adminUserDetails);

        RequestBuilder request = MockMvcRequestBuilders
            .post("/api/v1/authenticate")
            .contentType(MediaType.APPLICATION_JSON)
            .content(authBody);
    

控制器代码:

public class JwtAuthenticationController 
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

【问题讨论】:

【参考方案1】:

你有@WebMvcTest。

可用于 Spring MVC 测试的注解 在 Spring MVC 组件上。

您需要使用 @SpringBootTest(classes = Application.class) 并配置您的 MockMvc。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class JwtControllerTests 

    private MockMvc mockMvc;


    @MockBean
    private JwtUserDetailsService jwtUserDetailsService;

    @MockBean
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;


    @Before
    public void setup() 
        MockitoAnnotations.initMocks(this);
        this.mockMvc = MockMvcBuilders.standaloneSetup(new JwtAuthenticationController(authenticationManager,jwtUserDetailsService,jwtTokenUtil))
                .addInterceptors(interceptor)
                .setControllerAdvice(exceptionTranslator)
                .build();


    

 @Test

public void auth_Success() throws Exception 
        when(
                jwtUserDetailsService.loadUserByUsername(anyString())
        ).thenReturn(adminUserDetails);

        RequestBuilder request = MockMvcRequestBuilders
                .post("/api/v1/authenticate")
                .contentType(MediaType.APPLICATION_JSON)
                .content(authBody);

         mockMvc.perform(request).andExpect(status().isOk());
    

更改您的 JwtAuthenticationController 以接受构造函数的依赖项。

【讨论】:

同样的错误仍然由以下原因引起:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有 JwtTokenUtil' 类型的合格 bean 可用: 我更新了我的答案。我之前没有看到@WebMvcTest。 您知道这种方法与保留@WebMvcTest 但随后添加@Import(JwtTokenUtil.class) 相比如何使错误消失。 同理;唯一的区别是使用@Import,你包含显式的依赖关系,另一种方式你可以访问所有的spring上下文。 在你的方法中,如果我不需要明确引用 jwkTokenUtil,但控制器需要它,我还需要在测试类中自动装配它吗?

以上是关于如何在 MockMVC 中模拟一些 bean 而不是其他的?的主要内容,如果未能解决你的问题,请参考以下文章

mockmvc 模拟令牌不起作用并尝试在令牌库上进行验证

如何在 Spring MVC 中模拟安全上下文以进行测试

无标题

无标题

无标题

MockMVC的使用