spring-boot - 通过字段表达的不满足依赖——Springboot的Application,组件和测试类都在同一个包中
问题描述
我的理解是 SpringBootApplication 注解包含 ComponentScan
在Application.main()中发现并打印了bean,为什么单元测试找不到呢?
此单元测试失败:
org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为“com.pds.pdssr.etlfile.EtlFileServicesTest”的bean时出错:通过字段“etlFileServices”表示不满足的依赖关系;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有“com.pds.pdssr.etlfile.EtlFileServices”类型的合格 bean 可用:预计至少有 1 个有资格作为自动装配候选者的 bean。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)}
使用适当的调试级别,即“org.springframework.context.annotation”="debug" 我可以看到在组件扫描期间发现了 bean。
然而,单元测试的结果是:
[错误] getAll(com.pds.pdssr.etlfile.EtlFileServicesTest) 经过时间:0.007 s <<< 错误!org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为“com.pds.pdssr.etlfile.EtlFileServicesTest”的bean时出错:通过字段“etlFileServices”表示不满足的依赖关系;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有“com.pds.pdssr.etlfile.EtlFileServices”类型的合格 bean 可用:预计至少有 1 个有资格作为自动装配候选者的 bean。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)} 原因:org.springframework.beans.factory.NoSuchBeanDefinitionException:没有'com.pds.pdssr.etlfile.EtlFileServices 类型的合格bean ' 可用的:预计至少有 1 个 bean 有资格作为 autowire 候选者。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)}
应用程序:
package com.pds.pdssr.bootstrap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
//@EnableJpaRepositories("com.pds.pdsssr.jpa")
@SpringBootApplication
// @EntityScan("com.pds.pdssr.models")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
for (String name : applicationContext.getBeanDefinitionNames()) {
logger.info("bean: " + name);
}
}
}
组件:
包 com.pds.pdssr.bootstrap;
import java.util.List;
import javax.persistence.EntityManagerFactory;
import javax.transaction.Transactional;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.pds.pdssr.models.EtlFile;
@Repository
public class EtlFileServices {
@Autowired
private static EntityManagerFactory entityManagerFactory;
public SessionFactory getSessionFactory() {
SessionFactory sessionFactory = null;
if (entityManagerFactory == null) {
throw new IllegalStateException("entityManagerFactory is null");
}
sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
if (sessionFactory == null) {
throw new NullPointerException("factory is not a hibernate factory");
}
return sessionFactory;
}
@SuppressWarnings("unchecked")
public List<EtlFile> getAll() {
return getAll("etlFile",getSessionFactory().getCurrentSession());
}
@SuppressWarnings("rawtypes")
protected List getAll(String tableName, Session session) {
String queryText = "from " + tableName;
return getList(tableName, queryText, session);
}
@SuppressWarnings("rawtypes")
protected List getList(String tableName, String queryText, Session session) {
long start = System.nanoTime();
Query query = session.createQuery(queryText);
List result = query.list();
long end = System.nanoTime();
long millis = (end - start) / 1000000;
//logger.debug("table: " + tableName + " millis " + millis + " rows: " + result.size());
return result;
}
}
测试类:
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringRunner;
import com.pds.pdssr.bootstrap.EtlFileServices;
import com.pds.pdssr.models.EtlFile;
@RunWith(SpringRunner.class)
public class EtlFileServicesTest {
@Autowired
private EtlFileServices etlFileServices;
@Test
public void getAll() {
List<EtlFile> etlFiles = etlFileServices.getAll();
assertNotNull(etlFiles);
}
}
解决方案
原答案:
你需要有
@RunWith(SpringRunner.class)
@SpringBootTest(classes = YourMainClass.class)
在您的测试课程中。
基于评论的进一步回答
如果你真的想SessionFactory
在你的项目中拥有,你需要告诉spring框架明确地拥有SessionContext。可以通过添加来完成
spring.jpa.properties.hibernate.current_session_context_class = org.springframework.orm.hibernate5.SpringSessionContext
到你的配置文件。这是您的问题的一个工作示例。
HTH
推荐阅读
- javascript - 我想从 api 报价中获取数据
- encryption - 使用 Libsodium 和 SSL (HTTPS) 时的 Apple 出口合规性
- node.js - 我想在未来的日期/时间运行一个函数 - 一次 | nodejs - 后端任务?
- javascript - 使用 Spotify API 进行路由
- c# - 当将用户的答案与随机生成的代码进行比较时,程序认为无论输入什么,它们总是相同的
- php - “此路由不支持 PUT 方法。支持的方法:POST。” 托管后出错
- javascript - 将日期时间转换为 UTC 但保持相同的日期和时间组件
- django - Django:具有抽象基类的多种用户类型
- r - 如何在不重复代码的情况下操作多个条件
- python - 更改检查点中张量流变量的形状