Cucumber 步骤 - 使用持久性上下文测试 EJB 服务
Cucumber steps - testing an EJB service with a persistence context
我有一个使用 @PersistenceContext
和 EntityManager
的无状态 EJB,我正在编写一个黄瓜步骤定义 class,它使用此服务来执行测试查找用户的步骤根据提供的标准。
例如
@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'
和步骤定义 class
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
被注入了
通过 @PersistenceContext
.
我的问题是在步骤定义中我应该如何处理这种依赖关系?我应该模拟它并将这个模拟注入 UserService
,还是 UserService
有一个 EntityManager
的 setter 并使用 EntityManagerFactory
创建一个在 SearchStepsDefinitions
?
换句话说
@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,然后步骤 class 现在看起来像这样
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>
我有一个使用 @PersistenceContext
和 EntityManager
的无状态 EJB,我正在编写一个黄瓜步骤定义 class,它使用此服务来执行测试查找用户的步骤根据提供的标准。
例如
@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'
和步骤定义 class
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
被注入了
通过 @PersistenceContext
.
我的问题是在步骤定义中我应该如何处理这种依赖关系?我应该模拟它并将这个模拟注入 UserService
,还是 UserService
有一个 EntityManager
的 setter 并使用 EntityManagerFactory
创建一个在 SearchStepsDefinitions
?
换句话说
@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,然后步骤 class 现在看起来像这样
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>