2017-09-10 14 views
0

Tomie를 Intellij와 함께 사용하여 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 속성을 올바르게 추가하려면 어떻게해야합니까? 단위 테스트에 대한 TomEE 포함 된 컨테이너를 사용와

<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

내가 있었다 성공 : 여기 내 persistence.xml입니다. 외부 JUnit 리소스와 마찬가지로 @Rule을 사용하여 관리 할 수 ​​있으므로 Rule 클래스와 Embedded Tomie의 래퍼라는 두 클래스가 있습니다.

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); 
    } 
} 

을 보일 것이다 방법의 예이며, 당신이 두 시험에 중단 점을 배치 할 수 있으며, 서버 코드 엄밀히 말하면 단위 테스트라고 부르는 것이 좋지만 한 가지 구성 요소를 더 테스트 할 때이 유형의 테스트를 선호합니다. 완전히 기능적인 TomEE가 필요하기 때문에 많은 외부 종속성을 제공해야 할 것입니다. 제 경우에는 다음과 같습니다 :