私は春のフレームワークで初心者です。私は春のブートでユニットテストを構成することに問題があります。より正確には、ユニットテストを実行しながらスプリングのコンテキストをロードすることです。私はmaven multimoduleプロジェクト(チーム内)と協力して、これを行うための適切なソリューションを探しています。次のように私のプロジェクト構造の 一部は次のとおりです。Springブートmavenマルチモジュールプロジェクト - ユニットテスト(アプリケーションコンテキスト)
- ・コモンズ(モジュール、パッケージ:瓶、utilsのモジュール)
+ --- SRC
+ ---のpom.xml - 提案(モジュール、包装:POM)
- 提案-API(サブモジュール:インターフェース、DTO、包装:JAR)
- 提案マッピング(サブモジュール:エンティティ)
- 提案-SE rvice(サブモジュール:サービス、春のデータリポジトリ、DTO - - エンティティ<> DTOマッパーは、提案型のAPIと提案型マッピングのパッケージに依存します。jar)
+ --- SRC
+ ---メイン
+ --- Javaの
+ --- com.company.proposal.service
+ --- DeviceRepositoryService.java
+ --- DeviceMapper.java
+ --- ProposalRepositoryService.java
+ --- ProposalMapper.java
+ --- など多くのクラス...
+ ---テスト
+ --- Javaの
+ --- com.company.proposal.service
+ --- DeviceRepositoryServiceTest.java
+ --- ProposalRepositoryServiceTest。Javaの
+ --- ...
+ ---のpom.xml - 提案型スターター(サブモジュール:自動クラス、パッケージ化します。jar)
+ --- SRC
+ ---メイン
+ --- Javaの
+ --- com.company.proposal.configuration
+ --- ProposalAutoConfiguration.java
+ --- RemoteReportProcessorAutoConfiguration.java
+ ---その他の設定クラス...
+ ---資源
+ --- META-INF
+ - - spring.factories
+ --- application.properties
+ ---のpom.xml
- エントリポイント(モジュール、パッケージング:POM)
- エントリポイント-API(サブモジュール、パッケージング:JAR)
- エントリポイントサービス(サブモジュール、パッケージング:JAR)
- エントリ・ポイント・スターター(サブモジュール、パッケージング:wildflyにデプロイWAR)
- 他-モジュール...
- のpom.xml(ルートPOM)、私が書いた
例ユニットテスト(DeviceRepositoryServiceTest.java):
@RunWith(SpringRunner.class)
public class DeviceRepositoryServiceTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@MockBean
private DeviceRepository deviceRepository;
@Autowired
private DeviceMapper deviceMapper;
private DeviceRepositoryService deviceRepositoryService;
private final String imei = "123456789123456";
private final String producer = "samsung";
private final String model = "s5";
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
deviceRepositoryService = new DeviceRepositoryService(deviceRepository, deviceMapper);
}
@org.springframework.boot.test.context.TestConfiguration
static class TestConfiguration {
@Bean
public DeviceMapper deviceMapper() {
return new DeviceMapperImpl();
}
}
@Test
public void test_should_create_device() {
given(deviceRepository.findByImei(imei)).willReturn(null);
when(deviceRepository.save(any(Device.class))).thenAnswer((Answer) invocation -> invocation.getArguments()[0]);
DeviceSnapshot device = deviceRepositoryService.createOrFindDeviceByImei(imei, producer, model);
assertThat(device.getImei()).isEqualTo(imei);
assertThat(device.getProducer()).isEqualTo(producer);
assertThat(device.getModel()).isEqualTo(model);
verify(deviceRepository, times(1)).save(any(Device.class));
}
@Test
public void test_should_return_device() {
Device testDevice = createTestDevice();
given(deviceRepository.findByImei(imei)).willReturn(testDevice);
DeviceSnapshot actualDevice = deviceRepositoryService
.createOrFindDeviceByImei(testDevice.getImei(), testDevice.getProducer(), testDevice.getModel());
assertThat(actualDevice.getImei()).isEqualTo(testDevice.getImei());
assertThat(actualDevice.getProducer()).isEqualTo(testDevice.getProducer());
assertThat(actualDevice.getModel()).isEqualTo(testDevice.getModel());
verify(deviceRepository, times(0)).save(any(Device.class));
verify(deviceRepository, times(1)).findByImei(testDevice.getImei());
}
@Test
public void test_should_find_device() {
Device device = createTestDevice();
given(deviceRepository.findOne(device.getId())).willReturn(device);
DeviceSnapshot actualDevice = deviceRepositoryService.findDeviceById(device.getId());
DeviceSnapshot expectedDevice = deviceMapper.toDeviceSnapshot(device);
assertThat(actualDevice).isEqualTo(expectedDevice);
verify(deviceRepository, times(1)).findOne(device.getId());
}
@Test
public void test_should_find_device_by_pparams() {
Device device = createTestDevice();
Long proposalId = 1L, providerConfigId = 2L;
given(deviceRepository.findByProposalParams(proposalId, providerConfigId)).willReturn(device);
DeviceSnapshot actualDevice = deviceRepositoryService.findDeviceByProposalParams(proposalId, providerConfigId);
DeviceSnapshot expectedDevice = deviceMapper.toDeviceSnapshot(device);
assertThat(actualDevice).isEqualTo(expectedDevice);
verify(deviceRepository, times(1)).findByProposalParams(proposalId, providerConfigId);
}
@Test
public void test_should_throw_not_found_1() {
given(deviceRepository.findOne(anyLong())).willReturn(null);
this.thrown.expect(DeviceNotFoundException.class);
deviceRepositoryService.findDeviceById(1L);
}
@Test
public void test_should_throw_not_found_2() {
given(deviceRepository.findByProposalParams(anyLong(), anyLong())).willReturn(null);
this.thrown.expect(DeviceNotFoundException.class);
deviceRepositoryService.findDeviceByProposalParams(1L, 1L);
}
private Device createTestDevice() {
return Device.builder()
.id(1L)
.imei(imei)
.model(model)
.producer(producer)
.build();
}
}
あなたは私がコンテキストを定義するために@TestConfigurationアノテーションを使用見ることができるように、しかし、クラスDeviceRepositoryService
は非常にシンプルなので、コンテキスト定義も単純な2つの依存関係しかないためです。上記のクラスで
@Slf4j
@Service
@AllArgsConstructor
@Transactional
public class ProposalRepositoryService implements ProposalService {
private final ProposalRepository proposalRepository;
private final ProposalMapper proposalMapper;
private final ProposalRepositoryProperties repositoryProperties;
private final ImageProposalRepository imageProposalRepository;
private final ProviderConfigService providerConfigService;
...
}
は、より多くの依存関係があるとの事は、私はすべてのテスト(TestConfiguration注釈)用の構成コードの束を書きたくないんです。私はまた、短期的には以下のように見えたクラスProposalRepositoryService
をテストする必要があります。例えば。私がいくつかのサービスに依存関係を追加すると、ユニットテストクラスの半分を変更する必要があります。また、多くのコードが繰り返し実行されます。私はまた、ユニットテストコードがあるため、構成定義の醜いなっている例があります。
@TestPropertySource("classpath:application-test.properties")
public class RemoteReportProcessorRepositoryServiceTest {
@Autowired
private RemoteReportProcessorRepositoryService remoteReportProcessorRepositoryService;
@TestConfiguration //here, I don't want to write bunch of configuration code for every test
static class TestConfig {
@Bean
@Autowired
public RemoteReportProcessorRepositoryService remoteReportProcessorRepositoryService(RemoteReportMailService remoteReportMailService,
FtpsService ftpsService,
RemoteDailyReportProperties remoteDailyReportProperties,
RemoteMonthlyReportProperties remoteMonthlyReportProperties,
DeviceRepository deviceRepository,
ProposalRepository proposalRepository) {
return new RemoteReportProcessorRepositoryService(ftpsService, remoteReportMailService, remoteDailyReportProperties, remoteMonthlyReportProperties, deviceRepository, proposalRepository);
}
@Bean
@Autowired
public FtpsManagerService ftpsManagerService(FTPSClient ftpsClient, MailService mailService, FtpsProperties ftpsProperties) {
return new FtpsManagerService(ftpsClient, ftpsProperties, mailService);
}
@Bean
public FTPSClient ftpsClient() {
return new FTPSClient();
}
@Bean
@Autowired
public MailService mailService(MailProperties mailProperties, JavaMailSender javaMailSender, PgpProperties pgpProperties) {
return new MailManagerService(mailProperties, javaMailSender, pgpProperties);
}
@Bean
public JavaMailSender javaMailSender() {
return new JavaMailSenderImpl();
}
@Bean
@Autowired
public RemoteReportMailService remoteReportMailService(RemoteReportMailProperties remoteReportMailProperties,
JavaMailSender javaMailSender,
Session session,
PgpProperties pgpProperties) {
return new RemoteReportMailManagerService(remoteReportMailProperties, javaMailSender, session, pgpProperties);
}
@Bean
@Autowired
public Session getJavaMailReceiver(RemoteReportMailProperties remoteReportMailProperties) {
Properties properties = new Properties();
properties.put("mail.imap.host", remoteReportMailProperties.getImapHost());
properties.put("mail.imap.port", remoteReportMailProperties.getImapPort());
properties.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.imap.socketFactory.fallback", "false");
properties.setProperty("mail.imap.socketFactory.port", remoteReportMailProperties.getImapPort().toString());
properties.put("mail.imap.debug", "true");
properties.put("mail.imap.ssl.trust", "*");
return Session.getDefaultInstance(properties);
}
}
...
}
だから、私の質問はの束を記述することなく、春のブートMavenのマルチモジュールプロジェクト正しい方法でユニットテストのための春のコンテキストを設定する方法であります構成コード? また、maven multimoduleプロジェクトの処理方法について詳しく説明している記事へのリンクに感謝します。
共通の親クラスを作成することができます構成コードが含まれている同様のテストケース。 – 11thdimension
例を表示できますか?私はすべての構成コードを保持しているが、そのクラスは他のすべてのモジュール(循環依存性)に依存しなければならない1つのクラス(例えば、コモンズモジュールなど)を書くことができます。 – lukascode
親クラスのアプローチで試してください、私は循環依存の問題があるとは思わない。私は例を掲示しようとします – 11thdimension