Spring Boot/@JDBCTest - 没有 'com.fasterxml.jackson.databind.ObjectMapper' 类型的合格 bean 可用
Spring Boot/@JDBCTest - No qualifying bean of type 'com.fasterxml.jackson.databind.ObjectMapper' available
这里有点 Spring 引导菜鸟,非常感谢您的帮助!
我已经使用 JDBCTemplate 构建了一个 Spring 启动应用程序,运行 并且运行正常,没有错误或异常。
我已经制作了一个测试 class 并且想使用@JdbcTest 来测试我的 Dao 对象。但是,每次我 运行 测试时,我都会得到 java.lang.IllegalStateException: Failed to load ApplicationContext
。我的控制器 classes 似乎有问题。此 IllegalStateException 由以下原因引起:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'assetApiController' defined in file [/PATH/TO/FILE]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.fasterxml.jackson.databind.ObjectMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
我的测试class:
@JdbcTest
@Sql({"schema.sql", "test-data.sql"})
class AssetApiControllerTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
AssetDao assetDao;
@Test
void delete() throws DataAccessException {
assetDao.setJdbcTemplate(jdbcTemplate);
assetDao.deleteByPk(new AssetKey(1), null);
assertEquals(0, assetDao.selectAll(null).size());
}
}
我的道:
@Repository("assetDao")
public class AssetDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void deleteByPk (AssetKey assetKey, Connection con) throws DataAccessException {
jdbcTemplate.update("DELETE FROM Asset WHERE id = ? ", assetKey.getId());
}
}
我的控制器class:
@Controller
public class AssetApiController implements AssetApi {
private static final Logger log = LoggerFactory.getLogger(AssetApiController.class);
private final ObjectMapper objectMapper;
private final HttpServletRequest request;
@Autowired
private AssetDao assetDao;
@org.springframework.beans.factory.annotation.Autowired
public AssetApiController(ObjectMapper objectMapper, HttpServletRequest request) {
this.objectMapper = objectMapper;
this.request = request;
}
@Override
public ResponseEntity<Void> delete(@RequestBody AssetKey assetKey) {
try{
assetDao.deleteByPk(assetKey, null);
} catch (ApplicationException e) {
log.warn(e.getFormattedMessage(), e);
return new ResponseEntity<Void>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<Void>(HttpStatus.OK);
}
}
我的 JacksonConfig:
@Configuration
public class JacksonConfiguration {
@Bean
@ConditionalOnMissingBean(ThreeTenModule.class)
ThreeTenModule threeTenModule() {
ThreeTenModule module = new ThreeTenModule();
module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
return module;
}
}
还有两点可以帮助诊断:
我遵循了这个答案:。它解决了问题,但后来我得到了 HttpServletRequest 的等效错误:No qualifying bean found for dependency [javax.servlet.http.HttpServletRequest]
。所以根本问题没有得到解决。
当我尝试为 Asset 以外的实体生成测试时(例如 'Supplier' 与 SupplierController、SupplierDao),我得到相同的错误:Error creating bean with name 'assetApiController' defined in file
。这一定是因为assetApiController是第一个被扫描的controller,因为按字母顺序排列?
您好 :) 您有什么 spring 引导版本?总体而言,这似乎是一个通用的应用程序上下文配置问题。
我宁愿在开始测试之前稍微重构一下。在 Spring Boot 中使用 @Autowired 构造函数非常好。当您想测试时,它会让您的生活变得更加轻松。
- 重构 DAO class。
@Repository("assetDao")
public class AssetDao {
private final JdbcTemplate jdbcTemplate;
//handy you can put also validation here if all is good
//we will use it later in the test
@Autowired
public AssetDao (JdbcTemplate jdbcTemplate){
jdbcTemplate = jdbcTemplate;
}
public void deleteByPk (AssetKey assetKey, Connection con) throws DataAccessException
{
jdbcTemplate.update("DELETE FROM Asset WHERE id = ? ", assetKey.getId());
}
}
- 现在测试...您似乎是通过控制器测试 DAO 的?发生的事情是整个应用程序上下文想要与您的 dao 一起加载。你想要@Autowire。您必须在测试等中初始化 spring 上下文...因此会出现错误。如果你想专注于 DAO,你可以这样做:
@JdbcTest
@Sql({"schema.sql", "test-data.sql"})
class AssetDaoTest {
private AssetDao assetDao;
private JdbcTemplate template;
@Before
public void setup() {
template = new JdbcTemplate();
assetDao = new AssetDao(template);
}
@Test
void delete() throws DataAccessException {
assetDao.deleteByPk(new AssetKey(1), null);
assertEquals(0, assetDao.selectAll(null).size());
}
}
试一试,我的电脑上还没有运行。
这里有点 Spring 引导菜鸟,非常感谢您的帮助!
我已经使用 JDBCTemplate 构建了一个 Spring 启动应用程序,运行 并且运行正常,没有错误或异常。
我已经制作了一个测试 class 并且想使用@JdbcTest 来测试我的 Dao 对象。但是,每次我 运行 测试时,我都会得到 java.lang.IllegalStateException: Failed to load ApplicationContext
。我的控制器 classes 似乎有问题。此 IllegalStateException 由以下原因引起:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'assetApiController' defined in file [/PATH/TO/FILE]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.fasterxml.jackson.databind.ObjectMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
我的测试class:
@JdbcTest
@Sql({"schema.sql", "test-data.sql"})
class AssetApiControllerTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
AssetDao assetDao;
@Test
void delete() throws DataAccessException {
assetDao.setJdbcTemplate(jdbcTemplate);
assetDao.deleteByPk(new AssetKey(1), null);
assertEquals(0, assetDao.selectAll(null).size());
}
}
我的道:
@Repository("assetDao")
public class AssetDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void deleteByPk (AssetKey assetKey, Connection con) throws DataAccessException {
jdbcTemplate.update("DELETE FROM Asset WHERE id = ? ", assetKey.getId());
}
}
我的控制器class:
@Controller
public class AssetApiController implements AssetApi {
private static final Logger log = LoggerFactory.getLogger(AssetApiController.class);
private final ObjectMapper objectMapper;
private final HttpServletRequest request;
@Autowired
private AssetDao assetDao;
@org.springframework.beans.factory.annotation.Autowired
public AssetApiController(ObjectMapper objectMapper, HttpServletRequest request) {
this.objectMapper = objectMapper;
this.request = request;
}
@Override
public ResponseEntity<Void> delete(@RequestBody AssetKey assetKey) {
try{
assetDao.deleteByPk(assetKey, null);
} catch (ApplicationException e) {
log.warn(e.getFormattedMessage(), e);
return new ResponseEntity<Void>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<Void>(HttpStatus.OK);
}
}
我的 JacksonConfig:
@Configuration
public class JacksonConfiguration {
@Bean
@ConditionalOnMissingBean(ThreeTenModule.class)
ThreeTenModule threeTenModule() {
ThreeTenModule module = new ThreeTenModule();
module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
return module;
}
}
还有两点可以帮助诊断:
我遵循了这个答案:。它解决了问题,但后来我得到了 HttpServletRequest 的等效错误:
No qualifying bean found for dependency [javax.servlet.http.HttpServletRequest]
。所以根本问题没有得到解决。当我尝试为 Asset 以外的实体生成测试时(例如 'Supplier' 与 SupplierController、SupplierDao),我得到相同的错误:
Error creating bean with name 'assetApiController' defined in file
。这一定是因为assetApiController是第一个被扫描的controller,因为按字母顺序排列?
您好 :) 您有什么 spring 引导版本?总体而言,这似乎是一个通用的应用程序上下文配置问题。 我宁愿在开始测试之前稍微重构一下。在 Spring Boot 中使用 @Autowired 构造函数非常好。当您想测试时,它会让您的生活变得更加轻松。
- 重构 DAO class。
@Repository("assetDao")
public class AssetDao {
private final JdbcTemplate jdbcTemplate;
//handy you can put also validation here if all is good
//we will use it later in the test
@Autowired
public AssetDao (JdbcTemplate jdbcTemplate){
jdbcTemplate = jdbcTemplate;
}
public void deleteByPk (AssetKey assetKey, Connection con) throws DataAccessException
{
jdbcTemplate.update("DELETE FROM Asset WHERE id = ? ", assetKey.getId());
}
}
- 现在测试...您似乎是通过控制器测试 DAO 的?发生的事情是整个应用程序上下文想要与您的 dao 一起加载。你想要@Autowire。您必须在测试等中初始化 spring 上下文...因此会出现错误。如果你想专注于 DAO,你可以这样做:
@JdbcTest
@Sql({"schema.sql", "test-data.sql"})
class AssetDaoTest {
private AssetDao assetDao;
private JdbcTemplate template;
@Before
public void setup() {
template = new JdbcTemplate();
assetDao = new AssetDao(template);
}
@Test
void delete() throws DataAccessException {
assetDao.deleteByPk(new AssetKey(1), null);
assertEquals(0, assetDao.selectAll(null).size());
}
}
试一试,我的电脑上还没有运行。