Ich führe einige Diensttests durch und ich teste eine konkrete Klasse, die sich von einem erstreckt, der Generics verwendet.Mockito schlägt auf NoSuchMethodError fehl, da die Methode in der abstrakten Klasse ist, die generische Methode verwendet
Ein Beispiel Aufbau der Service-Schicht ist unten:
public abstract class AbstractService <E extends AbstractEntity, IT extends AbstractItem> {
public void deleteAllItems(E entity) {
List<IT> items = new ArrayList<IT>(entity.getItems());
for(IT item : items) {
//Yada, yada
}
}
}
public class Service extends AbstractService<Entity, Item> {
}
public class OtherService() {
@Inject
private ServiceManager serviceManager;
public void deleteItems(Entity e) {
serviceManager.getService().deleteAllItems(e);
}
}
Dann ist es zu testen ich folgendes haben:
public class Test {
private Service service;
private OtherService otherService;
private ServiceManager serviceManager;
@BeforeMethod
public void setup() {
serviceManager= mock(serviceManager.class);
service= mock(Service.class);
when(serviceManager.getService()).thenReturn(service);
otherService=injector.getInstance(OtherService.class);
}
@Test
public void test() {
Entity e = new Entity();
//Attach some items
otherService.deleteItems(e);
verify(service).deleteAllItems(e);
}
}
Dies sollte die OtherService
nennen, die (Wir existiert verwenden Injektion, um das Objekt zu erhalten), und rufen Sie dann die Methode deleteItems()
, die wiederum deleteAllItems()
auf der Service
aufrufen sollte. Bevor ich das Java-Generika umgesetzt hatte, das hat gut funktioniert, aber da ich das Java-Generika umgesetzt habe, schlägt der Mockito Test mit der folgenden Ausnahme:
java.lang.NoSuchMethodError: Service.deleteAllItems(Entity;)V at Test.test(Test.java:XXX) org.mockito.exceptions.misusing.UnfinishedVerificationException: Missing method call for verify(mock) here: -> at Test.test(Test.java:XXX)
Example of correct verification: verify(mock).doSomething()
Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified.
Welche klingt es nicht die Methode finden kann. Sollte ich stattdessen die abstrakte Klasse von AbstractService
verspotten oder gibt es noch etwas, das mir fehlt?
EDIT
Von dem, was ich habe die Mockito Innenleben zu sehen ist, erzeugt es ein Beispiel dafür:
public void AbstractService.deleteAllItems(Entity)
Für das MockitoMethod
Objekt, so dass Sinn, dass Service.deleteAllItems()
machen würde " wird nicht aufgerufen ", es scheint, Mockito nimmt an, dass nur die Basisklasse jemals aufgerufen wurde. So scheint es, dass ich stattdessen die Basisklasse verspotten muss. Ich werde weiter untersuchen, aber wenn jemand noch andere Ideen hat, ich bin offen für Vorschläge
Bei Gerätetests schlage ich vor, den 'Injektor' nicht zu verwenden. Verwenden Sie einen package-private-Konstruktor, um eine Instanz der zu testenden Klasse zu erstellen. – NamshubWriter
Gibt es einen bestimmten Grund für diesen @NamshubWriter? Wir verwenden Injection, um die Instanzen der verwendeten Objekte zu steuern, und es funktioniert für uns. Es ist einfach genug, die verspotteten Objekte an die Injektion zu binden und dann dem "Injektor" zu erlauben, die korrekte Klasse einzufügen. Wir hatten nur ein Problem mit dieser einen Variante. Auch, wie lösen Sie mehrere Schichten der Injektion? Es kann eine Menge Spottregeln geben, wenn Sie nicht vorsichtig sind, mit der Injektion können wir es an einer Stelle setzen und die anderen Objekte werden diese Instanzen benutzen. – Draken
Abhängigkeitsinjektion ist ideal für Ihre Produktionsserver/Binär-und für große Integrationstests. Bei Komponententests werden Ihre Tests verlangsamt, sind zerbrechlich und schwer zu verstehen. Es kann auch Code-Gerüche verbergen (wie Klassen mit zu vielen Abhängigkeiten). Tests sollten folgen KISS – NamshubWriter