2017-09-10 4 views
0

私はIntellijでTomEEを使ってEJB/JPA Beanをテストしています。私はthis answerを見て、テストするために組み込みのコンテナを使うべきだと私は見ました。私はthis other answer(同じ質問から)でArquillianを発見しましたが、コメントに記載されているように、それを設定するのは難しく、ユーザーフレンドリーではなく、私のような初心者が検索します。TomEEでEJBをテストするには?

残念ながら私はglassfish-embedded-all依存関係を回答していませんが、tomee-embeddedです。私はこのofficial tutorialを見て、上で答えたのと同様にJTAを使うべきです。しかし、なぜ?最後のリンクとして行う

、私はこのエラーを取得しました。

No EJBContainer provider available: no provider names had been found. 

次に、このanswerから@BeforeClass方法からコードの一部を使用して。私のテストは以下の通りです:

Properties properties = new Properties(); 
    properties.setProperty(EJBContainer.PROVIDER, "tomee-embedded"); 
    EJBContainer container = EJBContainer.createEJBContainer(properties); 
    AccountDao dao = (AccountDao) container.getContext().lookup("java:global/Test/AccountDao"); 

Testは、私のアプリケーション名で、AccountDaoは私がテストしたい私のStateless Beanです。しかし、今、私はこのエラーを取得しています:

Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: PG_CLASS 

を私はHSQLDBを使用していないが、私はこのエラーを抱えています。私のHibernate entityManagerを正しくインスタンス化するためにいくつかのpostgresqlプロパティを正しく追加するにはどうしたらいいですか?ここに私のpersistence.xmlです:

<persistence-unit name="unitName"> 
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> 
    <class>entity.PersistentEntity.Account</class> 
    <properties> 
     <property name="tomee.jpa.factory.lazy" value="true"/> 
     <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/> 
     <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/click10"/> 
     <property name="javax.persistence.jdbc.user" value="postgres"/> 
     <property name="javax.persistence.jdbc.password" value="postgres"/> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect"/> 
     <property name="hibernate.show_sql" value="true"/> 
     <property name="hibernate.format_sql" value="true"/> 
     <property name="hibernate.hbm2ddl.auto" value="update"/> 
    </properties> 
</persistence-unit> 

答えて

1

私はユニットテストのためのTomEE埋め込まれたコンテナを使用して成功を収めています。外部のJUnitリソースと同様に、@Ruleを使用して管理することができます。したがって、RuleクラスとEmbedded TomEEのラッパーという2つのクラスがあります。

TomEE Containerクラスのラッパークラス。埋め込みダービーデータソースとユーザを設定して、基本認証をテストできるようにします。

/** 
* class for starting an Embedded TomEE server which will scan the classpath and start the application. 
* The configuration configures an InMemory derby database, and tells JPA to create tables based on the Entity annotations 
* 
*/ 
public class EmbeddedTomEE { 

    public static final String USERNAME = "aUser"; 
    public static final String PASSWORD = "aPassword"; 
    private Container container; 

    public void start() { 
     Configuration configuration = new Configuration(); 
     Properties properties = new Properties(); 
     properties.setProperty("jdbc/UdDB", "new://Resource?type=DataSource"); 
     properties.setProperty("jdbc/UdDB.jdbcDriver", "org.apache.derby.jdbc.EmbeddedDriver"); 
     properties.setProperty("jdbc/UdDB.jdbcUrl", "jdbc:derby:memory:udb;create=true"); 
     properties.setProperty("jdbc/UdDB.username", "SA"); 
     properties.setProperty("jdbc/UdDB.password", ""); 
     properties.setProperty("jdbc/UdDB.jtaManaged", "true"); 
     properties.setProperty("persistence_unit.javax.persistence.schema-generation.database.action", "create"); 
     properties.setProperty("persistence_unit.javax.persistence.sql-load-script-source", "META-INF/testdata.sql"); 
     properties.setProperty("rest-persistence_unit.eclipselink.logging.level", "FINE"); //use 'FINE' for JPA logging 

     configuration.setProperties(properties); 
     // use a random port so we can have TomEE running parallel with tests 
     configuration.randomHttpPort(); 
     configuration.setWebXml("src/main/webapp/WEB-INF/web.xml"); 

     HashMap<String, String> users = new HashMap<>(); 
     users.put(USERNAME, PASSWORD); 
     configuration.setUsers(users); 
     HashMap<String, String> roles = new HashMap<>(); 
     roles.put("aUser", "user"); 
     configuration.setRoles(roles); 
     container = new Container(configuration).deployClasspathAsWebApp(); 
    } 

    public int getPort() { 
     return container.getConfiguration().getHttpPort(); 
    } 

    public void stop() { 
     container.close(); 
    } 
} 

各テストが実行される前に組み込みTomEEの起動を担当するJUnitルール。また、すべてのテストでコンテナの開始と停止のコストを避けるためのロジックがあります。このクラスは、アプリケーションのRESTサービスを呼び出すために使用できるJAX-RS WebClientも作成します。ここで

/** 
* JUnit rule for running an EmbeddedTomEE in memory. The rule has static state, this is to avoid starting and stopping the embedded container 
* with every test. Every time no test are running we start a timer, which is canceled if another test is started. This way the rule works well for a 
* single test run inside an IDE, and running multiple tests from Maven. 
* 
*/ 
public class EmbeddedTomEERule extends ExternalResource { 

    private static EmbeddedTomEE tomEE; 
    private static final AtomicInteger count = new AtomicInteger(); 
    private static Timer timer; 

    @Override 
    protected void before() throws Throwable { 
     startIfNeeded(); 
     if (timer != null) { 
      timer.cancel(); 
     } 
     count.incrementAndGet(); 
    } 

    @Synchronized 
    private void startIfNeeded() { 
     if (tomEE == null) { 
      tomEE = new EmbeddedTomEE(); 
      tomEE.start(); 
      Runtime.getRuntime().removeShutdownHook(new Thread(() -> tomEE.stop())); 
     } 
    } 

    @Override 
    protected void after() { 
     int runningTests = count.decrementAndGet(); 
     if (runningTests == 0) { 
      // stop after some time if no new test are started 
      timer = new Timer(); 
      timer.schedule(new StopEmbeddedContainer(), 10000); 
     } 
    } 

    public int getPort() { 
     return tomEE.getPort(); 
    } 

    /** 
    * creates a new WebClient that can request data from the specified path 
    */ 
    public WebClient getWebClient(String path, MediaType mediatype) { 
     WebClient client = WebClient.create("http://localhost:" + tomEE.getPort() + "/", Collections.singletonList(new JohnzonProvider()), 
       EmbeddedTomEE.USERNAME, EmbeddedTomEE.PASSWORD, null) 

       .path(path).accept(mediatype); 
     return client; 
    } 

    private static class StopEmbeddedContainer extends TimerTask { 
     @Override 
     public void run() { 
      tomEE.stop(); 
     } 
    } 
} 

は、このタイプのテストは、あなたがHTTP層でアプリケーションをテストすることができますテスト

public class ExampleTest { 

    @Rule 
    public EmbeddedTomEERule rule = new EmbeddedTomEERule(); 

    @Test 
    public void doTest() { 

     WebClient client = rule.getWebClient("some-endpoint", MediaType.APPLICATION_JSON_TYPE); 
     Output dto = client.get(Input.class); 
    } 
} 

をどのように見えるかの例であり、それはあなたが両方のテストにブレークポイントを配置することができますし、サーバーコード。技術的にはこれを単体テストと呼ぶこともありますが、その1つ以上のコンポーネントをテストする場合はこのタイプのテストが好きです。完全に機能するTomEEが必要なので、多くの外部依存関係を提供する必要があります。私の場合は次のようになります。

<dependency> 
    <groupId>org.apache.derby</groupId> 
    <artifactId>derby</artifactId> 
    <version>${derby.db.version}</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.apache.tomee</groupId> 
    <artifactId>openejb-core</artifactId> 
    <version>${openejb-core.version}</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.apache.tomee</groupId> 
    <artifactId>openejb-cxf-rs</artifactId> 
    <version>${openejb-core.version}</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.apache.tomee</groupId> 
    <artifactId>openejb-server</artifactId> 
    <version>${openejb-core.version}</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.apache.tomee</groupId> 
    <artifactId>openejb-rest</artifactId> 
    <version>${openejb-core.version}</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.apache.tomee</groupId> 
    <artifactId>tomee-embedded</artifactId> 
    <version>${openejb-core.version}</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.glassfish.web</groupId> 
    <artifactId>el-impl</artifactId> 
    <version>2.2</version> 
    <scope>test</scope> 
</dependency> 
関連する問題