java - Cucumber 步骤 - 使用持久性上下文测试 EJB 服务

标签 java jakarta-ee jpa testing cucumber

我有一个无状态 EJB,它使用 @PersistenceContextEntityManager ,我正在编写一个 cucumber 步骤定义类,该类使用此服务来执行根据提供的条件测试查找用户的步骤。

举个例子

@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public void add(String userName) {
        User user = new User(userName);
        em.persist(user);
    }    

    public List<User> findByName(String userName) {
        return em.createQuery("Select u from User as u WHERE u.name LIKE :userName").setParameter("userName", userName).getResultList();
    }

}

还有一个看起来像这样的功能文件

Feature: Search

    Given a user with the name 'Jason Statham'
        And another user with the name 'Bill Gates'
        And another user with the name 'Larry Page'
    When the customer searches for a user with the name 'Jason'
    Then 1 users should have been found
        And User 1 should have a name of 'Jason Statham'

和一个步骤定义类

 public class SearchStepsDefinitions {

   private List<User> userList = new ArrayList<>();
   private UserService userService = new UserService();

   @Given(value = ".+user with the name '(.+)'$")
   public void a_user_with_the_name(final String userName) {
       userService.add(userName);
   }

   @When(value = "^the customer searches for a user with the name '(.+)'$")
   public void the_customer_searches_for_a_user_with_the_name(final String name) {
       userList = userService.findByName(name); 
   }

   @Then(value = "(\\d+) users should have been found$")
   public void users_should_have_been_found(final int userCount) {
       assertThat(userList.size(), equalTo(userCount));
   }

   @Then(value = "User (\\d+) should have a name of '(.+)'$")
   public void should_have_a_name_of(final int position, final String name) {
       assertThat(userList.get(position - 1).getName(), equalTo(name)); 
   }

}

现在我明白了,由于服务是一个 EJB,所以 EntityManager被注入(inject) 通过@PersistenceContext .

我的问题是在步骤定义中我应该如何处理这种依赖性?我应该模拟它并将这个模拟注入(inject) UserService ,或者应该UserService有一个 EntityManager 的 setter 并使用 EntityManagerFactorySearchStepsDefinitions 中创建一个?

换句话说

@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public void add(String userName) {
        User user = new User(userName);
        em.persist(user);
    }    

    public List<User> findByName(String userName) {
        return em.createQuery("Select u from User as u WHERE u.name LIKE :userName").setParameter("userName", userName).getResultList();
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }

}

那么步骤定义就是这样的

public class SearchStepsDefinitions {

   private List<User> userList = new ArrayList<>();

   @Mock
   private EntityManager em;       

   @Inject
   @InjectMocks
   private UserService userService;

   @Given(value = ".+user with the name '(.+)'$")
   public void a_user_with_the_name(final String userName) {
       userService.add(userName);
   }

   @When(value = "^the customer searches for a user with the name '(.+)'$")
   public void the_customer_searches_for_a_user_with_the_name(final String name) {
       userList = userService.findByName(name); 
   }

   @Then(value = "(\\d+) users should have been found$")
   public void users_should_have_been_found(final int userCount) {
       assertThat(userList.size(), equalTo(userCount));
   }

   @Then(value = "User (\\d+) should have a name of '(.+)'$")
   public void should_have_a_name_of(final int position, final String name) {
       assertThat(userList.get(position - 1).getName(), equalTo(name)); 
   }

}

或者这个

public class SearchStepsDefinitions {

   private List<User> userList = new ArrayList<>();

   private UserService userService = new UserService();

   @Before
   public void setup() {
       userService.setEm(Persistence.createEntityManagerFactory("punit").createEntityManager());
   }

   @Given(value = ".+user with the name '(.+)'$")
   public void a_user_with_the_name(final String userName) {
       userService.add(userName);
   }

   @When(value = "^the customer searches for a user with the name '(.+)'$")
   public void the_customer_searches_for_a_user_with_the_name(final String name) {
       userList = userService.findByName(name); 
   }

   @Then(value = "(\\d+) users should have been found$")
   public void users_should_have_been_found(final int userCount) {
       assertThat(userList.size(), equalTo(userCount));
   }

   @Then(value = "User (\\d+) should have a name of '(.+)'$")
   public void should_have_a_name_of(final int position, final String name) {
       assertThat(userList.get(position - 1).getName(), equalTo(name)); 
   }

}

本质上我正在尝试做与 this example 相同的事情但我没有使用 Spring

或者也许另一种选择是不将服务作为 EJB 和 @Inject将 EntityManager 添加到其中

public class UserService {

    @Inject
    private EntityManager em;

    public void add(String userName) {
        User user = new User(userName);
        em.persist(user);
    }    

    public List<User> findByName(String userName) {
        return em.createQuery("Select u from User as u WHERE u.name LIKE :userName").setParameter("userName", userName).getResultList();
    }

}

然后步骤如下

 public class SearchStepsDefinitions {

   private List<User> userList = new ArrayList<>();

   @Inject
   private UserService userService;

   @Given(value = ".+user with the name '(.+)'$")
   public void a_user_with_the_name(final String userName) {
       userService.add(userName);
   }

   @When(value = "^the customer searches for a user with the name '(.+)'$")
   public void the_customer_searches_for_a_user_with_the_name(final String name) {
       userList = userService.findByName(name); 
   }

   @Then(value = "(\\d+) users should have been found$")
   public void users_should_have_been_found(final int userCount) {
       assertThat(userList.size(), equalTo(userCount));
   }

   @Then(value = "User (\\d+) should have a name of '(.+)'$")
   public void should_have_a_name_of(final int position, final String name) {
       assertThat(userList.get(position - 1).getName(), equalTo(name)); 
   }

}

我不太确定这些方法的优缺点?

最佳答案

经过多次挖掘,我发现我需要使用 EJBContainer,那么 Steps 类现在看起来像这样

 public class SearchStepsDefinitions {

   private Context context;
   private EJBContainer container;

   private List<User> userList = new ArrayList<>();

   private UserService userService;

   @cucumber.api.java.Before
   public void setup() {
       ejbContainer = EJBContainer.createEJBContainer();
       context = ejbContainer.getContext();

       userService = (UserService) context.lookup("java:global/classes/UserService");
   }

   @cucumber.api.java.After
   public void teardown() {
       ejbContainer.close();
   }

   @Given(value = ".+user with the name '(.+)'$")
   public void a_user_with_the_name(final String userName) {
       userService.add(userName);
   }

   @When(value = "^the customer searches for a user with the name '(.+)'$")
   public void the_customer_searches_for_a_user_with_the_name(final String name) {
       userList = userService.findByName(name); 
   }

   @Then(value = "(\\d+) users should have been found$")
   public void users_should_have_been_found(final int userCount) {
       assertThat(userList.size(), equalTo(userCount));
   }

   @Then(value = "User (\\d+) should have a name of '(.+)'$")
   public void should_have_a_name_of(final int position, final String name) {
       assertThat(userList.get(position - 1).getName(), equalTo(name)); 
   }

}

还需要的另一件事是 pom.xml 中的 ejb 容器。我使用 glassfish,具有这种依赖性。

<dependency>
    <groupId>org.glassfish.main.extras</groupId>
    <artifactId>glassfish-embedded-all</artifactId>
    <version>4.1</version>
</dependency>

关于java - Cucumber 步骤 - 使用持久性上下文测试 EJB 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31030380/

相关文章:

java - JBoss 5.0 是否有配置设置来控制 ear 文件的部署顺序?

java - JPA @OrderBy 在 @ElementCollection 中不起作用

java - 如何在spring data jpa中映射好友请求实体

java - jpa:repositories/@EnableJpaRepositories 与 @Repository - spring

java - 有状态 EJB 和跨客户端复制的相同 session

java - Subversion 与 Eclipse 中的多模块项目

java - Java 的 Date 类是怎么回事?这是一个已知的错误?

java - 如果凭据不正确,如何将用户重定向到另一个 JSP 页面

java - 使用远程接口(interface)正确配置 JSF EJB 应用程序

jakarta-ee - 如何在 Websphere 中测试已建立的 MQ 连接?