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

}

还有两点可以帮助诊断:

  1. 我遵循了这个答案:。它解决了问题,但后来我得到了 HttpServletRequest 的等效错误:No qualifying bean found for dependency [javax.servlet.http.HttpServletRequest]。所以根本问题没有得到解决。

  2. 当我尝试为 Asset 以外的实体生成测试时(例如 'Supplier' 与 SupplierController、SupplierDao),我得到相同的错误:Error creating bean with name 'assetApiController' defined in file。这一定是因为assetApiController是第一个被扫描的controller,因为按字母顺序排列?

您好 :) 您有什么 spring 引导版本?总体而言,这似乎是一个通用的应用程序上下文配置问题。 我宁愿在开始测试之前稍微重构一下。在 Spring Boot 中使用 @Autowired 构造函数非常好。当您想测试时,它会让您的生活变得更加轻松。

  1. 重构 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());
    }
}
  1. 现在测试...您似乎是通过控制器测试 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());
    }
}

试一试,我的电脑上还没有运行。