版本(SpringBoot不涉及/strong>):
Spring: 5.2.16
web-app / servlet API: 4.0
JUnit: 5.8
Spring MVC測驗對于回傳ResponseEntity<ReturnStatus>的控制器端點不起作用,其中ReturnStatus是一個具有適當getters/setters的POJO。 觸發的例外表明,JSON轉換對ReturnStatus不起作用。 我的研究表明,WebApplicationContext的基于注解的Java配置沒有被加載(因此Jackson的JSON轉換器沒有被識別)。 奇怪的是,在Tomcat的非測驗部署中,控制器端點作業正常,這可能是因為戰爭檔案中的web.xml被Tomcat決議了。
問題:
我如何調整此應用程式的 Spring MVC Test 的設定,以使 WebApplicationContext 的基于注解的 Java 配置能夠正確加載? 例如,是否可以在端點測驗邏輯(即 JUnit 測驗)中明確地做到這一點?
例外:
14:33: 57,765 WARN DefaultHandlerExceptionResolver: 199 - Resolved [org. springframework.http. converter.HttpMessageNotWritableException。No轉換器for [class com. acme.myapp.io.ReturnStatus] with preset Content-Type 'null']
14: 33: 57,765 DEBUG TestDispatcherServlet: 1131 - 完成 500 INTERNAL_SERVER_ERROR
Spring MVC應用程式包含以下配置:
Spring MVC應用程式包含以下配置。
test-context.xml,其中包含用于訪問資料存盤的Spring Bean配置:web.xml,它宣告和映射DispatcherServlet與WebApplicationContext的相關設定。- 在Java實作的
WebMvcConfigurer中基于注解的配置 。
來自test-context.xml的相關摘錄:
<context:component-scan base-package="com. acme.myapp"/>
<jpa:repositories base-package="com.acme.myapp.repos"/span>/>
<context:property-placeholder location="classpath:/application.properties" />/span>
<!--資料持久性配置-->
<bean id="transactionManager" class="org. springframework.orm.jpa.JpaTransactionManager">。
< property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="entityManagerFactory"/span> class="org. springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">。
< property name="dataSource" ref="dataSource" /> >。
<property name="jpaVendorAdapter">/span>
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/span>>/span>
<property name="showSql"/span> value="${db. showSql}" />
<property name="databasePlatform" value="${db. dialect}" />
<property name="generateDl" value="${db. generateDdl}" />
</bean>
</property>
<property name="packagesToScan"/span>>
<list>/span>
<value>com.acme.myapp.dao</value>/span>
</list>/span>
</property>/span>
</bean>/span>
<bean id="DataSource" class="org. apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"/span> value="${db. driver}" />
<property name="url" value="${db. url}" />
<property name="用戶名" value="${db. user}" />
<property name="password" value="${db. pass}" />
< property name="initialSize" value="2" />
< property name="maxActive" value="5" />
< property name="accessToUnderlyingConnectionAllowed" value="true"/>
</bean>
<!--在這里設定JVM系統屬性。我們這樣做主要是為了Hibernate日志。-->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"/span>>
<property name="targetObject">/span>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"/span>>
<property name="targetClass" value="java. lang.System" />
< property name="targetMethod" value="getProperties" />
</bean>
</property>
< property name="targetMethod" value="putAll" />
<property name="arguments">
<util:properties>
<prop key="org. jboss.logging.provider">slf4j</prop>
</util:properties>/span>
</property>/span>
</bean>
從web.xml(其中application-context.xml是我們的test-context.xml的生產版本)的相關摘錄:
<context-param>
<param-name>/span>contextConfigLocation</param-name>/span>
<param-value>classpath:application-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>/span>
</listener>
<servlet>/span>
<servlet-name>/span>central-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>/span>
<init-param>
<param-name>/span>contextConfigLocation</param-name>/span>
<param-value>com.acme.myapp.MyAppWebAppConfig</param-value>/span>
</init-param>
</servlet>/span>
<servlet-mapping>/span>
<servlet-name>central-dispatcher</servlet-name>
<url-pattern>/api/*</url-pattern>/span>
</servlet-mapping>/span>
摘自WebMvcConfigurer的Java實作(即,我們將Jackson JSON轉換器納入其中):
@EnableWebMvc
@Configuration[/span
@ComponentScan(basePackages = { "com.acme.myapp.controllers" })
public class MyAppWebAppConfig implements WebMvcConfigurerprivate static final Logger logger = LoggerFactory. getLogger(MyAppWebAppConfig.class)。
@Override
public void extendMessageConverters(List<HttpMessageConverter<? >> converters)
{
logger.debug("extendMessageConverters ...") 。
converters.add(new StringHttpMessageConverter()。
converters.add(new MappingJackson2HttpMessageConverter(new MyAppObjectMapper() )。
}
控制器的端點看起來像這樣(其中根部在/patients):
@RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ReturnStatus> readPatient(
@PathVariable("id") long id
)
{
ReturnStatus returnStatus = new ReturnStatus() 。
returnStatus.setVersionId("1.0"/span>)。
...
return new ResponseEntity<ReturnStatus>(returnStatus, httpStatus)。
}
使用JUnit5和MockMvc,端點測驗看起來是這樣的:
(location={"classpath:test-context.xml"/span>})
public class PatientControllerTest
{
private MockMvc mockMvc;
謝謝!
uj5u.com熱心網友回復:
這里有一些選擇,可能并不詳盡:
<mvc:annotation-driven>指令在test-context.xml。 例如: < bean id="myappObjectMapper"/span> class="com. acme.myapp.MyAppObjectMapper"/>。
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true"/span>>
<bean class="org.springframework.http. converter.json.MappingJackson2HttpMessageConverter"/span>>/span>
<constructor-arg ref="myappObjectMapper"/span>/>
</bean>
</mvc:message-converters>
</mvc:注釋驅動>
實際上,這個指令避免了加載MyAppWebAppConfig的需要,因為<mvc:annotation-driven>實際上是Java中注釋@EnableWebMvc的XML等價物。
- 實作
WebApplicationInitializer,從而有效地在Java中完成我們在web.xml中的配置。 例如:
public class MyAppWebApplicationInitializer implements WebApplicationInitializer
{
@Override
public void onStartup(ServletContext container)
{
XmlWebApplicationContext appCtx = new XmlWebApplicationContext()。
appCtx.setConfigLocation("classpath:application-context.xml") 。
container.addListener(new ContextLoaderListener(appCtx))。
AnnotationConfigWebApplicationContext dispatcherCtx = operator">= new AnnotationConfigWebApplicationContext()。
dispatcherCtx.register(MyAppWebAppConfig.class)。
ServletRegistration.Dynamic registration = container. addServlet("central-dispatcher", new DispatcherServlet(dispatcherCtx))。
registration.setLoadOnStartup(1)。
registration.addMapping("/api/*")。
}
對于這個解決方案,我們從專案中洗掉了web.xml;也許我們應該將對application-context.xml的參考也引數化。
注意,當我運行JUnit5測驗時,Spring沒有實體MyAppWebApplicationInitializer,相反,JUnit5加載的Spring背景關系是由@SpringJUnitWebConfig注釋參考的。因此,我建議將測驗相關的配置與test-context.xml放在一起,而將WebApplicationInitializer保留給生產。
我確信還有其他選擇,但我只探索了這兩種方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/329359.html
標籤:
上一篇:處理被退回的電子郵件
