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
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
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
Du musst angemeldet sein, um einen Kommentar abzugeben.
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. Deinen test könnte wie folgt Aussehen:
Tippfehler; sollte PersonServiceImpl. Sie instanziieren können. Nicht overhead - trivial. Die Anmerkungen haben, die zum instanziieren der Objekte. Es ist vertretbar, dass die Verarbeitung von Annotationen ist mehr Aufwand als einfach instanziieren Ihre Abhängigkeiten. Der springende Punkt ist, dass er nicht bekommen kann es arbeiten mit den Anmerkungen. Dies funktionieren wird.
Auch mit PersonServiceImpl er bekommen kann, es funktioniert mit anotations(Ursache, als er sagte, dass er bereits wusste, dass die Arbeit).
"Wie kann ich diese Arbeit machen ? "- anscheinend nicht.
"Die änderung der Art PersonService zu PersonServiceImpl in der PersonServiceTest anscheinend funktioniert der trick." - anscheinend ja.
InformationsquelleAutor duffymo