Unit-Test einer EJB mit Mockito, TestNG und OpenEJB

Habe ich die folgenden EJB ' s:

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

Und hier sind meine tests

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

Nun, will ich will zu tun ist, ersetzen Sie die RemotePersonService Umsetzung in PersonServiceImpl.java durch ein mock mit Mockito, und haben immer noch den gleichen Anruf in meinem testPersonService Methode.

Habe ich versucht:

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

Aber das funktioniert nicht. @Mock RemotePersonService wird nicht injiziert, die in den PersonService, und die wahre EJB wird immer noch benutzt.

Wie kann ich diese Arbeit machen ?

Nicht mit Anmerkungen für Ihre tests. Haben Sie einen Konstruktor, der Draht in allen Ihren Abhängigkeiten. Erstellen von mocks und passieren Sie es.
Die änderung der Art PersonService , PersonServiceImpl im PersonServiceTest scheinbar funktioniert der trick. Aber sollte es nicht möglich sein, verwenden Sie das interface statt Implementierung ?
Sie sollten explizit genannt werden hier. Wenn Sie PersonService wie Sie wissen, die Umsetzung injiziert wird und getestet wird? Mit PersonServiceImpl sagt Sie.
Aber das ist der Punkt - Sie sollten nicht zu wissen, den Typ, der injiziert.
Es ist nicht erlaubt, @InjectMocks in-Schnittstellen, denn Sie sollen die Prüfung von Beton-Klassen, die nicht Schnittstellen. So wie du kommentiert früher der Fall, ersetzen Sie die Schnittstelle, die verspottet werden, injiziert in eine konkrete Klasse

InformationsquelleAutor Yotus | 2015-07-14

Schreibe einen Kommentar