ArquillianチュートリアルのJPAを使ったテストを走らせるところをやってみる
TweetPosted on Saturday Jan 25, 2014 at 02:29PM in Technology
Arquillianチュートリアルのリモートコンテナでテストを走らせるところをやってみるの続きです。JPAを使ったテストを走らせるところをやってみます。今回も基本的にはチュートリアル[1]なぞるだけです。
環境
- JBoss AS 7.1.1.Final
- Eclipse Kepler SR1
- Apache Maven 2.2.1 (r801777; 2009-08-07 04:16:01+0900)
- Apple JDK6u65
- OS X 10.9.1
準備
チュートリアルにはGlassFishでテストを走らせる方法についても書いてありますが、ここではJBossで必要なものだけ用意します
何を作るか
この画像で選択されている4つのリソースを作ります
Game.java (エンティティクラス)
package org.arquillian.example; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; @Entity public class Game implements Serializable { private Long id; private String title; public Game() {} public Game(String title) { this.title = title; } @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } @NotNull @Size(min = 3, max = 50) public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @Override public String toString() { return "Game@" + hashCode() + "[id = " + id + "; title = " + title + "]"; } }
GamePersistenceTest.java (テストクラス)
このチュートリアルではEntityManagerを叩いているのはこのテストクラスだけです。本当はJPAを使ったEJBのテストをしたいところですが、とりあえずこれでやってみます
package org.arquillian.example; import java.util.List; import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.transaction.UserTransaction; import org.junit.Before; import org.junit.After; import org.junit.Test; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.junit.Assert; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.runner.RunWith; @RunWith(Arquillian.class) public class GamePersistenceTest { @Deployment public static Archive<?> createDeployment() { return ShrinkWrap.create(WebArchive.class, "test.war") .addPackage(Game.class.getPackage()) .addAsResource("test-persistence.xml", "META-INF/persistence.xml") .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") .addAsWebInfResource("jbossas-ds.xml"); } private static final String[] GAME_TITLES = { "Super Mario Brothers", "Mario Kart", "F-Zero" }; @PersistenceContext EntityManager em; @Inject UserTransaction utx; @Before public void preparePersistenceTest() throws Exception { clearData(); insertData(); startTransaction(); } private void clearData() throws Exception { utx.begin(); em.joinTransaction(); System.out.println("Dumping old records..."); em.createQuery("delete from Game").executeUpdate(); utx.commit(); } private void insertData() throws Exception { utx.begin(); em.joinTransaction(); System.out.println("Inserting records..."); for (String title : GAME_TITLES) { Game game = new Game(title); em.persist(game); } utx.commit(); // clear the persistence context (first-level cache) em.clear(); } private void startTransaction() throws Exception { utx.begin(); em.joinTransaction(); } @After public void commitTransaction() throws Exception { utx.commit(); } @Test public void shouldFindAllGamesUsingJpqlQuery() throws Exception { // given String fetchingAllGamesInJpql = "select g from Game g order by g.id"; // when System.out.println("Selecting (using JPQL)..."); List<Game> games = em.createQuery(fetchingAllGamesInJpql, Game.class).getResultList(); // then System.out.println("Found " + games.size() + " games (using JPQL):"); assertContainsAllGames(games); } private static void assertContainsAllGames(Collection<Game> retrievedGames) { Assert.assertEquals(GAME_TITLES.length, retrievedGames.size()); final Set<String> retrievedGameTitles = new HashSet<String>(); for (Game game : retrievedGames) { System.out.println("* " + game); retrievedGameTitles.add(game.getTitle()); } Assert.assertTrue(retrievedGameTitles.containsAll(Arrays.asList(GAME_TITLES))); } }
jbossas-ds.xml (データソース定義)
データソース定義をこのファイルに書いておけば、テスト実行する度に一時的にデータソース定義を行ってくれます。APサーバ側のコンソールをいじってデータソース定義をやる必要はありません。これは便利。
本当はPostgreSQLあたりを使ってリアルにレコードを確認したいところですが、簡単のためとりあえずチュートリアル通りに標準搭載のH2を使ってインメモリデータベースを使います
<?xml version="1.0" encoding="UTF-8"?> <datasources xmlns="http://www.jboss.org/ironjacamar/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.jboss.org/ironjacamar/schema http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd"> <datasource enabled="true" jndi-name="jdbc/arquillian" pool-name="ArquillianEmbeddedH2Pool"> <connection-url>jdbc:h2:mem:arquillian;DB_CLOSE_DELAY=-1</connection-url> <driver>h2</driver> </datasource> </datasources>
test-persistence.xml (永続化コンテキスト定義)
JTAトランザクションのJavaEEなJPAの定義ですね。JavaSEのと違ってエンティティクラス名の列挙は必要ありません。良い。
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="test"> <jta-data-source>jdbc/arquillian</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence>
テスト実行
- 前回同様、右クリック→Run As→JUnit Test
- Profileも前回同様JBossのremoteで
JUnit窓
ログ
16:22:40,034 INFO [org.jboss.as.repository] (management-handler-thread - 17) JBAS014900: Content added at location /Users/kyle/apps/jboss-as-7.1.1.Final/standalone/data/content/48/93a135faeb37e43d3d9346ea59cc2bfc3c784c/content 16:22:40,040 INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) JBAS015876: Starting deployment of "arquillian-service" 16:22:40,100 WARN [org.jboss.as.dependency.private] (MSC service thread 1-5) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.jmx:main") which may be changed or removed in future versions without notice. 16:22:40,101 WARN [org.jboss.as.dependency.private] (MSC service thread 1-5) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.server:main") which may be changed or removed in future versions without notice. 16:22:40,101 WARN [org.jboss.as.dependency.private] (MSC service thread 1-5) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.as.osgi:main") which may be changed or removed in future versions without notice. 16:22:40,102 WARN [org.jboss.as.dependency.private] (MSC service thread 1-5) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.jandex:main") which may be changed or removed in future versions without notice. 16:22:40,102 WARN [org.jboss.as.dependency.private] (MSC service thread 1-5) JBAS018567: Deployment "deployment.arquillian-service" is using a private module ("org.jboss.osgi.framework:main") which may be changed or removed in future versions without notice. 16:22:40,123 INFO [org.jboss.as.server] (management-handler-thread - 17) JBAS018559: Deployed "arquillian-service" 16:22:40,251 INFO [org.jboss.as.repository] (management-handler-thread - 18) JBAS014900: Content added at location /Users/kyle/apps/jboss-as-7.1.1.Final/standalone/data/content/ed/a8915f6ceb2f30ae6c44b37a827c3c0064d992/content 16:22:40,253 INFO [org.jboss.as.server.deployment] (MSC service thread 1-4) JBAS015876: Starting deployment of "test.war" 16:22:40,307 INFO [org.jboss.as.jpa] (MSC service thread 1-2) JBAS011401: Read persistence.xml for test 16:22:40,350 INFO [org.jboss.weld.deployer] (MSC service thread 1-7) JBAS016002: Processing weld deployment test.war 16:22:40,387 INFO [org.jboss.weld.deployer] (MSC service thread 1-15) JBAS016005: Starting Services for CDI deployment: test.war 16:22:40,401 INFO [org.jboss.as.arquillian] (MSC service thread 1-9) Arquillian deployment detected: ArquillianConfig[service=jboss.arquillian.config."test.war",unit=test.war,tests=[org.arquillian.example.GreeterTest, org.arquillian.example.GamePersistenceTest]] 16:22:40,402 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-2) JBAS010400: Bound data source [jdbc/arquillian] 16:22:40,403 INFO [org.jboss.as.jpa] (MSC service thread 1-2) JBAS011402: Starting Persistence Unit Service 'test.war#test' 16:22:40,498 INFO [org.hibernate.annotations.common.Version] (MSC service thread 1-2) HCANN000001: Hibernate Commons Annotations {4.0.1.Final} 16:22:40,503 INFO [org.hibernate.Version] (MSC service thread 1-2) HHH000412: Hibernate Core {4.0.1.Final} 16:22:40,505 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-2) HHH000206: hibernate.properties not found 16:22:40,506 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-2) HHH000021: Bytecode provider name : javassist 16:22:40,525 INFO [org.hibernate.ejb.Ejb3Configuration] (MSC service thread 1-2) HHH000204: Processing PersistenceUnitInfo [ name: test ...] 16:22:40,648 INFO [org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator] (MSC service thread 1-2) HHH000130: Instantiating explicit connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider 16:22:40,830 INFO [org.hibernate.dialect.Dialect] (MSC service thread 1-2) HHH000400: Using dialect: org.hibernate.dialect.H2Dialect 16:22:40,835 WARN [org.hibernate.dialect.H2Dialect] (MSC service thread 1-2) HHH000431: Unable to determine H2 database version, certain features may not work 16:22:40,838 INFO [org.hibernate.engine.jdbc.internal.LobCreatorBuilder] (MSC service thread 1-2) HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4 16:22:40,845 INFO [org.hibernate.engine.transaction.internal.TransactionFactoryInitiator] (MSC service thread 1-2) HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory 16:22:40,848 INFO [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (MSC service thread 1-2) HHH000397: Using ASTQueryTranslatorFactory 16:22:40,875 INFO [org.hibernate.validator.util.Version] (MSC service thread 1-2) Hibernate Validator 4.2.0.Final 16:22:41,079 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-2) HHH000227: Running hbm2ddl schema export 16:22:41,083 INFO [stdout] (MSC service thread 1-2) Hibernate: drop table Game if exists 16:22:41,083 INFO [stdout] (MSC service thread 1-2) Hibernate: drop sequence hibernate_sequence 16:22:41,090 ERROR [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-2) HHH000389: Unsuccessful: drop sequence hibernate_sequence 16:22:41,090 ERROR [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-2) シーケンス "HIBERNATE_SEQUENCE" が見つかりません Sequence "HIBERNATE_SEQUENCE" not found; SQL statement: drop sequence hibernate_sequence [90036-161] 16:22:41,090 INFO [stdout] (MSC service thread 1-2) Hibernate: create table Game (id bigint not null, title varchar(50) not null, primary key (id)) 16:22:41,091 INFO [stdout] (MSC service thread 1-2) Hibernate: create sequence hibernate_sequence start with 1 increment by 1 16:22:41,093 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-2) HHH000230: Schema export complete 16:22:41,113 INFO [org.jboss.weld.deployer] (MSC service thread 1-7) JBAS016008: Starting weld service for deployment test.war 16:22:41,239 INFO [org.jboss.web] (MSC service thread 1-6) JBAS018210: Registering web context: /test 16:22:41,248 INFO [org.jboss.as.server] (management-handler-thread - 18) JBAS018559: Deployed "test.war" 16:22:41,407 INFO [stdout] (pool-4-thread-4) Dumping old records... 16:22:41,501 INFO [stdout] (pool-4-thread-4) Hibernate: delete from Game 16:22:41,515 INFO [stdout] (pool-4-thread-4) Inserting records... 16:22:41,517 INFO [stdout] (pool-4-thread-4) Hibernate: call next value for hibernate_sequence 16:22:41,549 INFO [stdout] (pool-4-thread-4) Hibernate: call next value for hibernate_sequence 16:22:41,550 INFO [stdout] (pool-4-thread-4) Hibernate: call next value for hibernate_sequence 16:22:41,566 INFO [stdout] (pool-4-thread-4) Hibernate: insert into Game (title, id) values (?, ?) 16:22:41,568 INFO [stdout] (pool-4-thread-4) Hibernate: insert into Game (title, id) values (?, ?) 16:22:41,569 INFO [stdout] (pool-4-thread-4) Hibernate: insert into Game (title, id) values (?, ?) 16:22:41,573 INFO [stdout] (pool-4-thread-4) Selecting (using JPQL)... 16:22:41,584 INFO [stdout] (pool-4-thread-4) Hibernate: select game0_.id as id0_, game0_.title as title0_ from Game game0_ order by game0_.id 16:22:41,588 INFO [stdout] (pool-4-thread-4) Found 3 games (using JPQL): 16:22:41,588 INFO [stdout] (pool-4-thread-4) * Game@1954523691[id = 1; title = Super Mario Brothers] 16:22:41,589 INFO [stdout] (pool-4-thread-4) * Game@402776278[id = 2; title = Mario Kart] 16:22:41,589 INFO [stdout] (pool-4-thread-4) * Game@592449002[id = 3; title = F-Zero] 16:22:41,641 INFO [org.jboss.weld.deployer] (MSC service thread 1-14) JBAS016009: Stopping weld service for deployment test.war 16:22:41,643 INFO [org.jboss.as.jpa] (MSC service thread 1-14) JBAS011403: Stopping Persistence Unit Service 'test.war#test' 16:22:41,643 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-14) HHH000227: Running hbm2ddl schema export 16:22:41,644 INFO [stdout] (MSC service thread 1-14) Hibernate: drop table Game if exists 16:22:41,647 INFO [stdout] (MSC service thread 1-14) Hibernate: drop sequence hibernate_sequence 16:22:41,647 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-14) HHH000230: Schema export complete 16:22:41,648 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-8) JBAS010409: Unbound data source [jdbc/arquillian] 16:22:41,656 INFO [org.jboss.as.server.deployment] (MSC service thread 1-9) JBAS015877: Stopped deployment test.war in 40ms 16:22:41,664 INFO [org.jboss.as.repository] (management-handler-thread - 20) JBAS014901: Content removed from location /Users/kyle/apps/jboss-as-7.1.1.Final/standalone/data/content/ed/a8915f6ceb2f30ae6c44b37a827c3c0064d992/content 16:22:41,665 INFO [org.jboss.as.server] (management-handler-thread - 20) JBAS018558: Undeployed "test.war" 16:22:41,685 INFO [org.jboss.as.server.deployment] (MSC service thread 1-11) JBAS015877: Stopped deployment arquillian-service in 5ms 16:22:41,693 INFO [org.jboss.as.repository] (management-handler-thread - 17) JBAS014901: Content removed from location /Users/kyle/apps/jboss-as-7.1.1.Final/standalone/data/content/48/93a135faeb37e43d3d9346ea59cc2bfc3c784c/content 16:22:41,693 INFO [org.jboss.as.server] (management-handler-thread - 17) JBAS018558: Undeployed "arquillian-service"
備考
特に問題なさげですね。しかも速い。クラスの数も少なくアプリケーションアーカイブのサイズも小さいので当然かもしれませんが3〜4秒です。これならJPAのマニアックな機能を使った複雑な機能の実装とテストも怖くないですね。
というか本家のチュートリアル[1]がよくできてて日本語訳も読みやすいので読みましょう。
ちなみにチュートリアルにも書かれていますが埋め込みモードではJPAを使ったテストは動かないそうです。ただし埋め込みGlassFishは可。
続き
ArquillianをWildFly8.0.0.CR1で動かしてみる
参考文献
Tags: test