【发布时间】:2015-07-14 10:23:24
【问题描述】:
我有以下 EJB:
PersonService.java
@Local
public interface PersonService {
long countPersons();
}
PersonServiceImpl.java
@Stateless
public class PersonServiceImpl implements PersonService {
@EJB
private RemotePersonService remotePersonService;
@Override
public long countPersons() {
return remotePersonService.getAllPersons().size();
}
}
RemotePersonService.java
@Local
public interface RemotePersonService {
List<Person> getAllPersons();
}
RemotePersonServiceImpl.Java
@Stateless
public class RemotePersonServiceImpl {
@Override
public List<Person> getAllPersons() {
// Here, I normally call a remote webservice, but this is for the purpose of this question
List<Person> results = new ArrayList<Person>();
results.add(new Person("John"));
return results;
}
}
这是我的测试
AbstractTest.java
public abstract class AbstractTest {
private InitialContext context;
@BeforeClass(alwaysRun = true)
public void setUp() throws Exception {
System.setProperty("java.naming.factory.initial", "org.apache.openejb.client.LocalInitialContextFactory");
Properties properties = new Properties();
properties.load(getClass().getResourceAsStream("/unittest-jndi.properties"));
context = new InitialContext(properties);
context.bind("inject", this);
}
@AfterClass(alwaysRun = true)
public void tearDown() throws Exception {
if (context != null) {
context.close();
}
}
}
PersonServiceTest.java
@LocalClient
public class PersonServiceTest extends AbstractTest {
@EJB
private PersonService personService;
@Test
public void testPersonService() {
long count = personService.countPersons();
Assert.assertEquals(count, 1l);
}
}
现在,我想做的是将 PersonServiceImpl.java 中的 RemotePersonService 实现替换为使用 Mockito 的模拟,并且在我的 testPersonService 方法中仍然有相同的调用。
我试过了:
PersonServiceTest.java
@LocalClient
public class PersonServiceTest extends AbstractTest {
@Mock
private RemotePersonService remotePersonService;
@EJB
@InjectMocks
private PersonService personService;
@BeforeMethod(alwaysRun = true)
public void setUpMocks() {
MockitoAnnotations.initMocks(this);
List<Person> customResults = new ArrayList<Person>();
customResults.add(new Person("Alice"));
customResults.add(new Person("Bob"));
Mockito.when(remotePersonService.getAllPersons()).thenReturn(customResults);
}
@Test
public void testPersonService() {
long count = personService.countPersons();
Assert.assertEquals(count, 2l);
}
}
但这不起作用。在PersonService中没有注入@Mock RemotePersonService,仍然使用真正的EJB。
我怎样才能完成这项工作?
【问题讨论】:
-
不要在测试中使用注释。有一个构造函数来连接你的所有依赖项。创建模拟并将它们传递给它。
-
在 PersonServiceTest 中将类型 PersonService 更改为 PersonServiceImpl 显然可以解决问题。但是不应该使用接口而不是实现吗?
-
你应该在这里明确。如果您使用
PersonService,您如何知道注入并测试了哪个实现?使用PersonServiceImpl会告诉你这一点。 -
但这就是重点——您不必知道注入的类型。
-
不允许@InjectMocks 进入接口,因为你应该测试具体的类而不是接口。因此,正如您之前评论的那样,您应该将模拟注入的接口替换为具体的类
标签: java ejb testng mockito openejb