Java 使用Mockito、TestNG和OpenEJB对EJB进行单元测试
我有以下EJB: PersonService.java PersonServiceImpl.java RemotePersonService.java PersonServiceTest.javaJava 使用Mockito、TestNG和OpenEJB对EJB进行单元测试,java,ejb,testng,mockito,openejb,Java,Ejb,Testng,Mockito,Openejb,我有以下EJB: PersonService.java PersonServiceImpl.java RemotePersonService.java PersonServiceTest.java 现在,我想做的是用Mockito的mock替换PersonServiceImpl.java中的RemotePersonService实现,并且在我的testPersonService方法中仍然有相同的调用 我试过: PersonServiceTest.java @LocalClient 公共类Per
现在,我想做的是用Mockito的mock替换PersonServiceImpl.java中的RemotePersonService实现,并且在我的testPersonService方法中仍然有相同的调用 我试过: PersonServiceTest.java
@LocalClient
公共类PersonServiceTest扩展了AbstractTest{
@嘲弄
专用RemotePersonService RemotePersonService;
@EJB
@注射模拟
私人私人服务;
@BeforeMethod(alwaysRun=true)
公共void setUpMocks(){
initMocks(this);
List customResults=new ArrayList();
customResults.add(新人(“Alice”);
customResults.add(新用户(“Bob”);
Mockito.when(remotePersonService.getAllPersons())。然后返回(customResults);
}
@试验
公共void testPersonService(){
long count=personService.countPersons();
Assert.assertEquals(计数,2l);
}
}
但这不起作用。@Mock-RemotePersonService没有注入PersonService,并且仍然使用真正的EJB
我如何才能做到这一点?不要在测试中使用注释。有一个将连接所有依赖项的构造函数
@Stateless
public class PersonServiceImpl implements PersonService {
@EJB
private RemotePersonService remotePersonService;
// Let your test instantiate a mock service and wire it into your test instance using this constructor.
public PersonServiceImpl(RemotePersonService rps) {
this.remotePersonService = rps;
}
@Override
public long countPersons() {
return remotePersonService.getAllPersons().size();
}
}
创建模拟并将其传递给它。您的测试可能如下所示:
@LocalClient
public class PersonServiceTest extends AbstractTest {
@Test
public void testPersonService() {
RemotePersonService mockRemotePersonService = Mockito.mock(RemotePersonService.class);
List<Person> customResults = new ArrayList<Person>();
customResults.add(new Person("Alice"));
customResults.add(new Person("Bob"));
Mockito.when(mockRemotePersonService.getAllPersons()).thenReturn(customResults);
PersonService personService = new PersonServiceImpl(mockRemotePersonService);
long count = personService.countPersons();
Assert.assertEquals(count, 2l);
}
}
@LocalClient
公共类PersonServiceTest扩展了AbstractTest{
@试验
公共void testPersonService(){
RemotePersonService mockRemotePersonService=Mockito.mock(RemotePersonService.class);
List customResults=new ArrayList();
customResults.add(新人(“Alice”);
customResults.add(新用户(“Bob”);
Mockito.when(mockRemotePersonService.getAllPersons())。然后返回(customResults);
PersonService PersonService=新PersonService MPL(mockRemotePersonService);
long count=personService.countPersons();
Assert.assertEquals(计数,2l);
}
}
我在类上使用setter,并查找ejb
private ServicioAsyncMessaging servicioNotificaciones;
我删除getter上的@EJB-->和
public ServicioAsyncMessaging getServicioNotificaciones() {
if(servicioNotificaciones == null){
servicioNotificaciones = (ServicioAsyncMessaging)Lookup.getEjb(EjbJndiConstantes.EJB_SERVICIO_ASYNC_MSG);
}
return servicioNotificaciones;
}
public void setServicioNotificaciones(ServicioAsyncMessaging servicioNotificaciones) {
this.servicioNotificaciones = servicioNotificaciones;
}
查找结果包括:
public static Object getEjb(String lookupName){
Object t = null;
try {
Context ctx = new InitialContext();
t= ctx.lookup(lookupName);
} catch (NamingException e) {
log.error("getEjb | Error {}",e.getMessage(),e);
}
return t;
}
通过这些更改,mockito-->在setter上注入mock。不要在测试中使用注释。有一个将连接所有依赖项的构造函数。创建模拟并将其传递给它。在PersonService测试中将PersonService类型更改为PersonServiceImpl显然可以做到这一点。但是,难道不能使用接口而不是实现吗?这里应该明确说明。如果使用
PersonService
如何知道注入了哪个实现并进行了测试?使用PersonServiceImpl
可以告诉您这一点。但这就是问题所在-您不必知道注入的类型。不允许@InjectMock注入接口,因为您应该测试的是具体类而不是接口。因此,正如您之前所评论的,您应该用一个具体的类替换mock被注入的接口,这是行不通的,因为PersonService是一个接口,您不能实例化它们。此外,编写构造函数或setter仅用于单元测试以注入mock,这只是一点开销,因为可以使用注释注入它们;应该是PersonServiceImpl。你可以举例说明。不是开销——微不足道。注释也必须实例化对象。有争议的是,处理注释比简单地实例化依赖项的开销更大。关键是他无法让它与注释一起工作。这将起作用。使用PersonServiceImpl他可以让它与anotations一起工作(因为他说他已经开始工作了)。“在PersonServiceTest中将类型PersonService更改为PersonServiceImpl显然起到了作用。”-显然是的。我可以在测试中使用具体的类PersonServiceImpl使其工作,但我想知道是否有可能改用这个接口。但显然,由于Mockito是如何注入mocks的,所以这样做从本质上来说是不可能的。
@LocalClient
public class PersonServiceTest extends AbstractTest {
@EJB
private PersonService personService;
@Test
public void testPersonService() {
long count = personService.countPersons();
Assert.assertEquals(count, 1l);
}
}
@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);
}
}
@Stateless
public class PersonServiceImpl implements PersonService {
@EJB
private RemotePersonService remotePersonService;
// Let your test instantiate a mock service and wire it into your test instance using this constructor.
public PersonServiceImpl(RemotePersonService rps) {
this.remotePersonService = rps;
}
@Override
public long countPersons() {
return remotePersonService.getAllPersons().size();
}
}
@LocalClient
public class PersonServiceTest extends AbstractTest {
@Test
public void testPersonService() {
RemotePersonService mockRemotePersonService = Mockito.mock(RemotePersonService.class);
List<Person> customResults = new ArrayList<Person>();
customResults.add(new Person("Alice"));
customResults.add(new Person("Bob"));
Mockito.when(mockRemotePersonService.getAllPersons()).thenReturn(customResults);
PersonService personService = new PersonServiceImpl(mockRemotePersonService);
long count = personService.countPersons();
Assert.assertEquals(count, 2l);
}
}
private ServicioAsyncMessaging servicioNotificaciones;
public ServicioAsyncMessaging getServicioNotificaciones() {
if(servicioNotificaciones == null){
servicioNotificaciones = (ServicioAsyncMessaging)Lookup.getEjb(EjbJndiConstantes.EJB_SERVICIO_ASYNC_MSG);
}
return servicioNotificaciones;
}
public void setServicioNotificaciones(ServicioAsyncMessaging servicioNotificaciones) {
this.servicioNotificaciones = servicioNotificaciones;
}
public static Object getEjb(String lookupName){
Object t = null;
try {
Context ctx = new InitialContext();
t= ctx.lookup(lookupName);
} catch (NamingException e) {
log.error("getEjb | Error {}",e.getMessage(),e);
}
return t;
}