使用Mockito,TestNG和OpenEJB对EJB进行单元测试

时间:2015-07-14 10:23:24

标签: java ejb testng mockito openejb

我有以下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);
    }
}

现在,我想要做的是使用Mockito通过模拟替换 PersonServiceImpl.java 中的RemotePersonService实现,并且仍然在我的 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);
    }
}

但这不起作用。 @Mock RemotePersonService未在PersonService中注入,并且仍在使用真正的EJB。

我该如何使用?

2 个答案:

答案 0 :(得分:2)

不要在测试中使用注释。有一个构造函数将连接所有依赖项。

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

答案 1 :(得分:0)

我在类上使用 setter,并查找 ejb

      private ServicioAsyncMessaging servicioNotificaciones;

我删除了@EJB --> 和 getter

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

查找es:

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 上注入模拟。