【问题标题】:Spring Boot/@JDBCTest - No qualifying bean of type 'com.fasterxml.jackson.databind.ObjectMapper' availableSpring Boot/@JDBCTest - 没有可用的“com.fasterxml.jackson.databind.ObjectMapper”类型的合格 bean
【发布时间】:2020-11-27 11:52:29
【问题描述】:

这里有一点 Spring Boot 新手,非常感谢任何帮助!

我已经使用 JDBCTemplate 构建了一个 Spring Boot 应用程序,该应用程序可以正常运行,没有错误或异常。

我已经制作了一个测试类,想使用@JdbcTest 来测试我的Dao 对象。但是,每次我运行测试时,我都会得到java.lang.IllegalStateException: Failed to load ApplicationContext。我的 Controller 类似乎有问题。此 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: {}

我的测试课:

@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());
    }
   }

我的控制器类:

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

 }                       

我的杰克逊配置:

@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. 我遵循了这个答案:https://stackoverflow.com/a/32842962/11853066。它解决了这个问题,但后来我得到了 HttpServletRequest 的等效错误:No qualifying bean found for dependency [javax.servlet.http.HttpServletRequest]。所以根本问题没有得到解决。

  2. 当我尝试为 Asset 以外的实体(例如,带有 SupplierController、SupplierDao 的“供应商”)生成测试时,我得到了同样的错误:Error creating bean with name 'assetApiController' defined in file。这一定是因为assetApiController是第一个被扫描的控制器,因为字母顺序?

【问题讨论】:

    标签: java spring-boot junit jdbctemplate


    【解决方案1】:

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

    1. 重构 DAO 类。
    @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());
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 2020-01-31
      • 2018-11-08
      • 2023-03-12
      • 1970-01-01
      • 2018-04-20
      • 2014-07-29
      • 2019-02-04
      • 2019-02-23
      • 1970-01-01
      相关资源
      最近更新 更多