【问题标题】:How to load application context for testing Spring application with JUnit 4?如何加载应用程序上下文以使用 JUnit 4 测试 Spring 应用程序?
【发布时间】:2021-06-23 08:36:16
【问题描述】:

我有一个 Spring 应用程序(不是 Spring Boot),我在其中使用 Spring Data JPA 和基于注释的 Java 配置。我正在尝试对创建自定义保存方法的存储库片段(JUnit 4)进行单元测试,但我无法正确加载所需的上下文和 bean 来运行测试:

[main] INFO org.springframework.test.context.support.DefaultTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener]
[main] INFO org.springframework.test.context.support.DefaultTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@87f383f, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@4eb7f003, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@eafc191, org.springframework.test.context.support.DirtiesContextTestExecutionListener@612fc6eb, org.springframework.test.context.transaction.TransactionalTestExecutionListener@1060b431, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@612679d6, org.springframework.test.context.event.EventPublishingTestExecutionListener@11758f2a]
[main] INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
[main] INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 96ms. Found 3 JPA repository interfaces.
[main] INFO org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'repositoryConfig' of type [com.example.app.config.RepositoryConfig$$EnhancerBySpringCGLIB$$4ffca507] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[main] ERROR org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@eafc191] to prepare test instance [com.example.app.test.tests.UserDaoTests@37313c65]
java.lang.NoClassDefFoundError: org.springframework.beans.FatalBeanException

我应该如何正确加载应用程序上下文?

UserDaoTests

@ActiveProfiles("dev")
@ContextConfiguration(loader=AnnotationConfigContextLoader.class, classes= {RepositoryConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
public class UserDaoTests {

private UserRepository userRepository;

@Autowired
private DataSource dataSource;

@Autowired
public void setUserRepository (UserRepository userRepository) {
    this.userRepository = userRepository;
}

private User user1 = new User("user", "userpass", true);

@Before
public void init() {
    System.out.println("Before running tests: init");
    JdbcTemplate jdbc = new JdbcTemplate(dataSource);
    jdbc.execute("delete from sec.authorities");
    jdbc.execute("delete from sec.users");
}

@Test
public void testExists () {
    userRepository.save(user1);
    System.out.println("Users created, test exists");
    assertTrue("User should exist", userRepository.existsByUsername("user"));
    assertFalse("User should not exist", userRepository.existsByUsername("abcdefghj"));
}
}

存储库配置

@Configuration
@ComponentScan("com.example.app.dao")
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {
        "com.example.app.dao"
}, entityManagerFactoryRef = "entityManagerFactory",
        transactionManagerRef = "transactionManager")
public class RepositoryConfig {
    
    @Profile("production")
    @Bean(name = "dataSource")
    public DataSource dataSource() {
        JndiDataSourceLookup lookup = new JndiDataSourceLookup();
        return lookup.getDataSource("java:jboss/datasources/postgresqlDS");
    }
    
    @Profile("dev")
    @Bean(name = "dataSource")
    public DataSource jdbcDataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setConnectionProperties(jdbcProperties().toString());
        return dataSource();
    }
    
    
   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      LocalContainerEntityManagerFactoryBean emf 
        = new LocalContainerEntityManagerFactoryBean();
      emf.setDataSource(dataSource());
      emf.setPackagesToScan(new String[] { "com.example.app.dao" });

      JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
      emf.setJpaVendorAdapter(vendorAdapter);
      emf.setJpaProperties(hibernateProperties());

      return emf;
   }
    
    private final Properties hibernateProperties() {
       //...
    }
    
    private final Properties jdbcProperties() {
        Properties jdbcProperties = new Properties();
        jdbcProperties.setProperty("driverClassName", "${jdbc.driver}");
        jdbcProperties.setProperty("url", "${jdbc.url}");
        jdbcProperties.setProperty("username", "${jdbc.username}");
        jdbcProperties.setProperty("password", "${jdbc.password}");
        return jdbcProperties;
    }
    
    @Bean
    public TransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        transactionManager.setDataSource(dataSource());
        return transactionManager;
    }
    
    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptiontranslator() {
        return new PersistenceExceptionTranslationPostProcessor();
    }
}

用户存储库

public interface UserRepository extends CustomizedSave<User>, CrudRepository<User, Long> {

    Optional<User> findByUsername(String username);
    Boolean existsByUsername(String username);
}

CustomizedSaveImpl

@Repository
public class CustomizedSaveImpl implements CustomizedSave<User>{    
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    
    @PersistenceContext
    EntityManager em;
    
    public CustomizedSaveImpl() {
        System.out.println("successfully loaded users DAO");
    }

    public User save (User user) {
        //...
    }   
}

【问题讨论】:

  • 我觉得,你应该把@Repository注解放在UserRepository接口上
  • @code_mechanic UserRepository 只是一个接口,实现是由 Spring Data JPA 生成的,因此我认为这不是问题。该应用程序有效,只有测试无法运行。
  • 我认为,您的问题与this 有关,因为您的错误有类似的错误消息。

标签: java spring spring-data-jpa


【解决方案1】:

这是由于创建循环引用的错字: jdbcDataSource() 应该是 return datasource 而不是 return dataSource();

由于其中一个 dataSource bean 指向另一个而引发异常。

【讨论】:

    猜你喜欢
    • 2013-02-03
    • 2018-07-11
    • 2015-04-27
    • 2013-02-08
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多