Spring 启动多个数据库通过集成测试导致 NoSuchBeanDefinitionException

时间:2021-07-16 09:00:58

标签: spring-boot unit-testing jpa

通过将应用程序配置为使用两个数据源实例,它会在我的集成测试之一中导致问题,并显示以下消息 - “通过方法 'entityManagerFactoryBean' 参数 0 表示的依赖项不满足;嵌套异常是 org.springframework.beans.factory。 NoSuchBeanDefinitionException:没有可用的“org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder”类型的合格 bean:预计至少有 1 个 bean 符合自动装配候选条件。依赖注释:{}"

这是存储两个数据库实例信息的 bean:

@Component
public class DataSourceRouting extends AbstractRoutingDataSource {
    private final DataSourcePrimeConfig dataSourcePrimeConfig;
    private final DataSourceSecondConfig dataSourceSecondConfig;
    private final DataSourceContextHolder dataSourceContextHolder;

    public DataSourceRouting(DataSourceContextHolder dataSourceContextHolder, DataSourcePrimeConfig dataSourcePrimeConfig,
                             DataSourceSecondConfig dataSourceSecondConfig) {
        this.dataSourcePrimeConfig = dataSourcePrimeConfig;
        this.dataSourceSecondConfig = dataSourceSecondConfig;
        this.dataSourceContextHolder = dataSourceContextHolder;

        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put(DataSourceEnum.DATASOURCE_PRIME, dataSourceOneDataSource());
        dataSourceMap.put(DataSourceEnum.DATASOURCE_SECOND, dataSourceTwoDataSource());
        this.setTargetDataSources(dataSourceMap);
        this.setDefaultTargetDataSource(dataSourceOneDataSource());
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return this.dataSourceContextHolder.getBranchContext();
    }

    public DataSource dataSourceOneDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(dataSourcePrimeConfig.getUrl());
        dataSource.setUsername(dataSourcePrimeConfig.getUsername());
        dataSource.setPassword(dataSourcePrimeConfig.getPassword());
        return dataSource;
    }

    public DataSource dataSourceTwoDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(dataSourceSecondConfig.getUrl());
        dataSource.setUsername(dataSourceSecondConfig.getUsername());
        dataSource.setPassword(dataSourceSecondConfig.getPassword());
        return dataSource;
    }
}

这里是配置类:

@Configuration
@EnableJpaRepositories(basePackages = "test.project.repository", transactionManagerRef = "transcationManager", entityManagerFactoryRef = "entityManager")
@EnableTransactionManagement
@RequiredArgsConstructor
@DependsOn("dataSourceRouting")
public class DataSourceConfig {
    private final DataSourceRouting dataSourceRouting;

    @Bean
    @Primary
    public DataSource dataSource() {
        return dataSourceRouting;
    }

    @Bean(name = "entityManager")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(dataSource()).packages("test.project").build();
    }

    @Bean(name = "transcationManager")
    public JpaTransactionManager transactionManager(
            @Autowired @Qualifier("entityManager") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
        return new JpaTransactionManager(entityManagerFactoryBean.getObject());
    }
}

这是失败的测试:

@SpringBootTest
@Import(value = DataSourceConfig.class)
@RunWith(SpringRunner.class)
@ActiveProfiles("test")
public class MailBodyProviderServiceTest {
    @Autowired
    private MailService mailService;

    @Autowired
    private ReportService reportService;

    @MockBean
    private JPATransactionDataRepository jpaTransactionDataRepository;

    @Autowired
    private MailBodyBuilder builder;

    @Autowired
    private DataSourceRouting dataSourceRouting;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private LocalContainerEntityManagerFactoryBean entityManagerFactoryBean;

    @Autowired
    private JpaTransactionManager jpaTransactionManager;

    @Autowired
    private EntityManagerFactoryBuilder entityManagerFactoryBuilder;

    @Rule
    public SmtpServerRule smtpServerRule = new SmtpServerRule(2525);

    @Test
    public void shouldSendSingleMail() throws MessagingException {

        when(this.jpaTransactionDataRepository.mapTransactionData()).thenReturn(generateReportData());
        mailService.sendEmail(new ReportEvent(this, "report event", EventType.CREDIT_CARD));

        MimeMessage[] receivedMessages = smtpServerRule.getMessages();
        assertEquals(3, receivedMessages.length);

        MimeMessage current = receivedMessages[0];
        String contentType = current.getContentType();
        assertTrue(contentType.contains("multipart"));
    }

    private static Map<Date, List<TransactionDto>> generateReportData(){

        Date today = new Date();

        List<Object[]> objects = new ArrayList<>();
        Object[] object1 = new Object[] { today, AuthStatus.AUTH_CONFIRMED.name(), ProcessingType.DIRECT.name(), BigDecimal.valueOf(10l)};
        Object[] object2 = new Object[] { today, AuthStatus.AUTH_REJECTED.name(), ProcessingType.DIRECT.name(), BigDecimal.valueOf(10l)};
        Object[] object3 = new Object[] { new Date(today.getTime() + (1000 * 60 * 60 * 24)), AuthStatus.AUTH_CANCELED.name(), ProcessingType.TAN.name(), BigDecimal.valueOf(10l)};
        Object[] object4 = new Object[] { new Date(today.getTime() + (1000 * 60 * 60 * 24)), AuthStatus.AUTH_FAILED.name(), ProcessingType.TAN.name(), BigDecimal.valueOf(10l)};
        objects.add(object1);
        objects.add(object2);
        objects.add(object3);
        objects.add(object4);

        return TransactionMapper.mapFromDatabaseQuery(objects);
    }
}

我尝试使用 @TestConfiguration,也排除 DataSourceConfig,但没有任何帮助。希望有人知道我做错了什么或错过了什么:)

0 个答案:

没有答案