注释 @ActiveProfile 在 Spring 应用程序中不起作用

Annotations @ActiveProfile doesn't work in a Spring app

我没有在这个应用程序中使用 spring-boot。 我正在测试配置文件以在集成测试中使用不同的数据源。

我有如下实体用户:

@Table(name = "user_inf")
@Entity
@NamedQuery(name="User.findById", query="select u from User u where u.id=:id")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long id;

    @Column(name = "userName", length = 25)
    private String userName;

    @Column(name = "userEmail", unique = true, length = 320)
    private String userEmail;
}

对于那个实体我有服务和 dao(服务只调用 dao 方法)

用户道:

@Repository
@Transactional
public class UserDaoImpl implements UserDao {

    @PersistenceContext
    private EntityManager entityManager;
    @Override
    public User findById(Long id) {
        TypedQuery<User> query = entityManager.createNamedQuery("User.findById", User.class);
        query.setParameter("id", id);
        return query.getSingleResult();
    }
}

用户服务:

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserDao userDao;
    @Override
    public User getUser(Long id) {
        return userDao.findById(id);
    }
}

@Configuration
@PropertySource(value = {"classpath:database/jdbc.properties"})
@EnableTransactionManagement
@ComponentScan({"com.example.test.repository", "com.example.test.service"})
public class SpringConfig {

    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH = "hibernate.max_fetch_depth";
    private static final String PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE = "hibernate.jdbc.fetch_size";
    private static final String PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE = "hibernate.jdbc.batch_size";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String ENTITY_MANAGER_PACKAGES_TO_SCAN = "com.example.test.entity";

    @Autowired
    private Environment env;


    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));
        return dataSource;
    }

    @Bean
    @Profile("test")
    public DataSource dataSourceForTest() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.test.url"));
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager jpaTransactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryBean.getObject());
        return transactionManager;
    }

    private HibernateJpaVendorAdapter vendorAdaptor() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setShowSql(true);
        return vendorAdapter;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource mainDataSource) {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setJpaVendorAdapter(vendorAdaptor());
        entityManagerFactoryBean.setDataSource(mainDataSource);
        entityManagerFactoryBean.setPackagesToScan(ENTITY_MANAGER_PACKAGES_TO_SCAN);
        entityManagerFactoryBean.setJpaProperties(jpaHibernateProperties());
        return entityManagerFactoryBean;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    private Properties jpaHibernateProperties() {
        Properties properties = new Properties();
        properties.put(PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH, env.getProperty(PROPERTY_NAME_HIBERNATE_MAX_FETCH_DEPTH));
        properties.put(PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE, env.getProperty(PROPERTY_NAME_HIBERNATE_JDBC_FETCH_SIZE));
        properties.put(PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE, env.getProperty(PROPERTY_NAME_HIBERNATE_JDBC_BATCH_SIZE));
        properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
        properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
        properties.put("hibernate.hbm2ddl.auto", "none");
        return properties;
    }

}

属性 用于数据源和休眠 (jdbc.properties) 的文件包含以下内容:

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdatabase
jdbc.username=Bruce
jdbc.password=givanchy

jdbc.test.url=jdbc:mysql://localhost:3306/testdatabase1

hibernate.max_fetch_depth = 3
hibernate.jdbc.fetch_size = 50
hibernate.jdbc.batch_size = 10
hibernate.show_sql = true
hibernate.dialect = org.hibernate.dialect.MySQL8Dialect

申请入口点:

public class EntryClass {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = applicationContext.getBean("userServiceImpl", UserServiceImpl.class);
        User user =userService.getUser(1L);
        System.out.println("userName is "+user.getUserName());
    }
}

它正常工作。 但是在测试源 我只有一项服务测试可以了解配置文件的工作原理

@SpringJUnitConfig(SpringConfig.class)
@ActiveProfiles("test")
class UserServiceImplTest {
    @Autowired
    private UserService userService;

    @Test
    void getUser() {
        User user = userService.getUser(5L);
        Assertions.assertEquals("Vector", user.getUserName());
    }
}

我得到“没有合格的 bean”异常,因为有两个数据源类型的 bean,但我设置了它应该使用哪个配置文件?你能解释为什么它不起作用吗?

正常启动时,不会创建具有 'test' 配置文件的数据源 bean。 (因为没有设置测试配置文件。)

当您 运行 将其作为测试时,将创建两个数据源 bean。默认创建是因为它没有任何条件,另一个是因为它用测试配置文件注释。

只需将 @Profile("!test") 添加到默认 bean。这样只有在测试配置文件未激活时才会创建它。