[Java][Spring] Spring Boot 1.4 -> 1.2 ダウングレードメモ
こんなことをするひとはいないと思いますが、せっかく苦しんだのでメモしておきます。
この文章の表記について
1.4: 1.4の場合のやりかたです。
1.2: 1.2の場合のやりかたです。
実装関係
@EntityScan
1.4: org.springframework.boot.autoconfigure.domain.EntityScan
1.2: org.springframework.boot.orm.jpa.EntityScan
DI
1.4: 自明であれば@Autowired
を付けなくてもDIしてくます。
1.2: @Autowired
付けましょう。
テスト関係
テストランナー
1.4: @RunWith(SpringRunner.class)
1.2: @RunWith(SpringJUnit4ClassRunner.class)
Springを使ったテスト
1.4: @SpringBootTest
を付ける
1.2: @SpringApplicationConfiguration(classes = アプリケーションクラス)
を付ける
http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/SpringApplicationConfiguration.html
データベース統合テスト
1.4: @DataJpaTest
をテストクラスに付ける。
1.2: ちと大変。
@DataJpaTest
はこんなことをしてくれているそうです。
- インメモリデータベースを設定
- Hibernate/Spring Data/Datasourceを設定
-
@EntityScan
を実行 - SQLログを有効化
全部がんばらないといけないかと思いましたが、これだけのことをやれば大丈夫そうです。
-
@EntityScan
、@EnableJpaRepositories
を付けたアプリケーションコンテキストクラスを作成。 -
TestEntityManager
クラスを作成(1.4からぱくる) -
TestEntityManager
を返すBeanを作成(1.4からぱくる) - テストクラスに
@Transactional
と@SpringApplicationConfiguration
を付ける。
順番にやっていきます。
@EntityScan
、@EnableJpaRepositories
を付けたアプリケーションコンテキストクラスを作成
TestApplication.java
@SpringBootApplication
@EnableJpaRepositories(レポジトリクラスの場所)
@EntityScan(エンティティクラスの場所)
@EnableJpaAuditing // これは今回関係ない
public class TestApplication {
}
TestEntityManager
クラスを作成(1.4からぱくる)
元ソースはここにあります。
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/
TestEntityManager.java
public class TestEntityManager {
private final EntityManagerFactory entityManagerFactory;
public TestEntityManager(EntityManagerFactory entityManagerFactory) {
Assert.notNull(entityManagerFactory, "EntityManagerFactory must not be null");
this.entityManagerFactory = entityManagerFactory;
}
public <E> E persist(E entity) {
getEntityManager().persist(entity);
return entity;
}
public void flush() {
getEntityManager().flush();
}
public <E> E persistAndFlush(E entity) {
persist(entity);
flush();
return entity;
}
public void detach(Object entity) {
getEntityManager().detach(entity);
}
public <E> E find(Class<E> entityClass, Object primaryKey) {
return getEntityManager().find(entityClass, primaryKey);
}
public final EntityManager getEntityManager() {
EntityManager manager = EntityManagerFactoryUtils
.getTransactionalEntityManager(this.entityManagerFactory);
Assert.state(manager != null, "No transactional EntityManager found");
return manager;
}
}
TestEntityManager
を返すBeanを作成(1.4からぱくる)
TestEntityManagerConfigure.java
@Configuration
@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)
public class TestEntityManagerConfigure {
@Bean
@ConditionalOnMissingBean
public TestEntityManager testEntityManager(
EntityManagerFactory entityManagerFactory) {
return new TestEntityManager(entityManagerFactory);
}
}
テストクラスに@Transactional
と@SpringApplicationConfiguration
を付ける
MySomeRepositoryTest.java
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestApplication.class)
@Transactional
public class MySomeRepositoryTest {
@Autowired
private MySomeRepository instance;
@Autowired
private TestEntityManager em;
@Test
public void testSomeMethod {
// ...
}
}
モック化したインスタンスをインジェクトする
1.4: モック化したいインスタンス変数に@MockBean
を付ける
1.2: モック化したインスタンスを返す@Bean
を定義して@Primary
を付ける
1.4の場合
MySomeTest.java
@MockBean
private MyTargetClass mock;
1.2の場合
特定の@Configurationクラスだけ有効になるように、@Profileを付けています。
MySomeTest.java
@ActiveProfiles("MySomeTest")
public class MySomeTest {
@Autowired
private MyTargetClass mock;
}
MySomeTestConfig.java
@Configuration
@Profile("MySomeTest")
public class MySomeTestConfig {
@Bean
@Primary
public MyTargetClass myTargetClass() {
return Mockito.mock(MyTargetClass.class);
}
}
旅は続く。。。
また何か発見があったら追記していきます。