当前位置: 首页 > 知识库问答 >
问题:

从JUnit运行时Spring不自动连接

吉凯捷
2023-03-14

我正在测试ControllerAdvice类,其中EncodeUtil是自动连接的,当我使用JUnit测试运行时,它总是被解析为Null,当通过Spring Boot应用程序运行时,没有问题,我缺少什么?

@ControllerAdvice
public class Base64EncodedResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Autowired
    private EncodeUtil encodeUtil;

    @Override
    public boolean supports(MethodParameter returnType, 
                            Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body,
                                  MethodParameter returnType,
                                  MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> converterType,
                                  ServerHttpRequest request,
                                  ServerHttpResponse response) {

        if(returnType.getMethod().getName().equalsIgnoreCase("doPNMImage"))
        {
           encodeUtil.encodeBase64(body);
           response.getHeaders().add("ENCODE_TYPE", "Base64");
        }
        else return body;
    }
}

这是我的Junit课程,我有

@ExtendWith(SpringExtension.class)
@WebMvcTest(PNMImageController.class)
@AutoConfigureMockMvc
public class Base64EncodedResponseBodyAdviceTest {

    @Mock
    private EncodeUtil encodeUtil;

    @InjectMocks
    PNMImageController pnmImageController;

    @BeforeEach
    void init(){
      MockitoAnnotations.initMocks(pnmImageController);
      mockMvc = MockMvcBuilders.standaloneSetup(pnmImageController)
            .setControllerAdvice(Base64EncodedResponseBodyAdvice.class)
            .build();
    }

    @Test
    public void getAuthorizeTest() throws Exception {
        ReflectionTestUtils.setField(encodeUtil, "salt", SALT);
        Mockito.when(this.encodeUtil.encodeBase64()).thenReturn(TEST_BASE64_STR);
        mockMvc.perform(post("http://localhost:8080/image/doPNMImage"))
                .andExpect(status().isOk())
                .andExpect(content().string(TEST_BASE64_STR))
                .andExpect(header().string("ENCODE_TYPE", "Base64"));
    }
}

测试失败与空指针异常

Request processing failed; nested exception is java.lang.NullPointerException: Cannot invoke "com.ylm.cnpl.core.util.EncodeUtil.encodeBase64(String)" because "this.encodeUtil" is null
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException: Cannot invoke "com.ylm.cnpl.core.util.encodeBase64(String)" because "this.encodeUtil" is null
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    

共有3个答案

袁霍英
2023-03-14

请添加@SpringBootTest更多信息:https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/html/boot-features-testing.html#boot-具有测试Spring Boot应用程序的功能,您需要指定要加载@ContextConfiguration的配置(https://docs.spring.io/spring-boot/docs/1.4.0.M3/reference/htmlsingle/#boot-功能测试spring启动应用程序(检测配置)

阎兴为
2023-03-14

当您尝试测试一个控制器和controllerAdvice时,使用@WebMvcTest(PNMImageController.class)

通过@WebMvcTest,您可以依靠Spring来创建所需的控制器。您试图用@InjectMocks创建第二个,但无法构建Spring尝试构建的那个。

请参阅@WebMvcTest javadoc

使用此注释将禁用完全自动配置,而只应用与MVC测试相关的配置(即@Controller、@ControllerAdvice、@JsonComponent、Converter/GenericConverter、Filter、WebMVCConfiguer和HandlerMethodArgumentResolver bean,但不应用@Component、@Service或@Repository bean)。

您需要向Spring提供EncodeUtil。由于您打算将其用作模拟,因此正确的注释是@MockBean

其次,创建mockMvc的一个实例。不需要这样做-您显式地编写了@AutoConfigureMockMvc,因此可以将其自动连接到测试中。事实上,@WebMvcTest是用@AutoConfigureMockMvc注释的,所以在测试中不需要它。@extendedwith(SpringExtension.class)也是如此。

更新代码

@WebMvcTest(PNMImageController.class)
public class Base64EncodedResponseBodyAdviceTest {

    @MockBean
    private EncodeUtil encodeUtil;

    @Autowired
    MockMvc mockMvc;


    @Test
    public void getAuthorizeTest() throws Exception {
        // ReflectionTestUtils.setField(encodeUtil, "salt", SALT);
        Mockito.when(this.encodeUtil.encodeBase64()).thenReturn(TEST_BASE64_STR);
        mockMvc.perform(post("http://localhost:8080/image/doPNMImage"))
                .andExpect(status().isOk())
                .andExpect(content().string(TEST_BASE64_STR))
                .andExpect(header().string("ENCODE_TYPE", "Base64"));
    }
}

除此之外:

  • 将盐场设置在该区域看起来可疑。您不需要在模拟上设置字段

如果将您的测试更改为@SpringBootTest不是一个好办法:SpringBootTest用于集成测试,它将使您的整个应用程序加速。当然,这将完成工作-您的控制器也将被旋转,但您应该努力使测试尽可能精简-仅旋转所需的控制器将使您的测试更快、更不脆弱。

施知
2023-03-14

@WebMvcTest-javadoc:

使用此注释将禁用完全自动配置,而只应用与MVC测试相关的配置(即@Controller、@ControllerAdvice、@JsonComponent、Converter/GenericConverter、Filter、WebMVCConfiguer和HandlerMethodArgumentResolver bean,但不应用@Component、@Service或@Repository bean)。

如果我们想在测试中把EncodeUtil作为bean:导入(配置),配置/组件扫描它。

>

为了保持测试上下文“苗条”,我们应该:

>

  • 为受影响的bean指定一个(主)配置

    或/和专用的"测试"配置,最简单的:

    @ExtendWith(SpringExtension.class)
    @WebMvcTest(PNMImageController.class)
    @AutoConfigureMockMvc
    public class Base64EncodedResponseBodyAdviceTest {
    
      @Configuration
      static class CustomTestConfig {
        @Bean
        EncodeUtil  ...               
      }
      ...
    } 
    

    如果我们想要@InjectMocks工作,我们应该(尝试)@MockBean而不是@Mock。。。@Mock、@MockBean和Mockito之间的区别。mock()。。。@Mock和@injectmock之间的区别。。。

    在spring测试中,我会使用:(org.springfr…)<代码>@MockBean和@Autowired!;)

  •  类似资料:
    • 我尝试使用以下代码模拟我的Runtime.getRuntime(): 但是我有以下错误:

    • 如何测试使用JdbcTemplate和SimpleJDBCall的repository类,如下所示 这就是我尝试过的 下面是测试代码和存储库代码,我使用的是Spring Boot最新版本junit5和mockito。我已经尝试了下面的解决方案,但可以让它工作 带Spring JdbcTemplate的SimpleJDBCall的Mockito 下面是存储库代码@repository public

    • 我有一个应用程序,公开Websocket/SockJS/Stomp服务器endpoint,并想运行一个JUnit测试,运行客户端(JavaSTOMP客户端,也来自Spring)对它,以测试发送功能。 我有一个测试,如 在这里,我从 https://github.com/jhalterman/concurrentunit 中使用了Water,其效果基本上是将测试的主线程延迟到辅助线程调用reachi

    • 另一个,如果我有另一个应用程序使用相同的使用者组,所有的分区会被重新分配到该应用程序吗?

    • 当我运行junit测试时,控制台打印此异常: 基本测试对象如下 而 JUnit 方法就像这样: 我的项目是JavaEE项目,使用maven管理lib,使用spring-manage-beans。 我的开发环境是: Mac OS X Yosetime 10.10.4 EclipseJavaEE IDE for Web Developers(版本:Mars Release(4.5.0)) Maven插

    • 我想尝试嵌入式数据库测试我的DAO对象在spring应用程序。 在应用程序上下文中,我有以下标记: 我的JUnit测试类需要使用这个bean: 一切正常(创建了“DataSourceEmbedded”bean),但当我试图在PartnerDAOTest类中自动调用它们时,spring抛出了以下异常: testSavePartner(Sandbox.PartnerDaoTest):创建名为“Sand