Vraag bespotten van een methode die generieken met jokertekens retourneert met mockito


Ik gebruik mockito 1.9.5. Ik heb de volgende code:

public class ClassA  {

public List<? extends MyInterface> getMyInterfaces() {
    return null;
}

public static void testMock() {
    List<MyInterface> interfaces = new ArrayList<>();
    ClassA classAMock = mock(ClassA.class);
    when(classAMock.getMyInterfaces()).thenReturn(interfaces);      
}

Ik krijg een compilatiefout voor de thenReturn(interfaces) gezegde:

"The method thenReturn(List<capture#1-of ? extends MyInterface>) in the type 
 OngoingStubbing<List<capture#1-of ? extends MyInterface>> is not applicable for the arguments 
 (List<MyInterface>)"

Echter, wanneer ik de thenAnswer methode van mockito, krijg ik de fout niet. Kan iemand me vertellen wat er aan de hand is? Waarom krijg ik de foutmelding wanneer ik de thenReturn methode? Is er een andere manier om dit probleem op te lossen wanneer ClassA wordt geleverd door een derde partij en kan niet worden gewijzigd?


43
2018-04-11 07:21


oorsprong


antwoorden:


BEWERK : Met ingang van Mockito 1.10.x worden generieke typen die zijn ingesloten in de klasse nu door Mockito gebruikt voor deepstubs. d.w.z.

public interface A<T extends Observer & Comparable<? super T>>  {
  List<? extends B> bList();
  T observer();
}

B b = deep_stubbed.bList().iterator().next(); // returns a mock of B ; mockito remebers that A returns a List of B
Observer o = deep_stubbed.observer(); // mockito can find that T super type is Observer
Comparable<? super T> c = deep_stubbed.observer(); // or that T implements Comparable

Mockito probeert zijn best om typegegevens te krijgen die de compiler insluit, maar wanneer wissen wordt toegepast, kan mockito niets anders doen dan een spot Object.


origineel : Nou dat is meer een kwestie van generieke medicijnen dan van Mockito. Voor generieke geneesmiddelen moet u lezen wat Angelika Langer schreef over hen. En lees voor het huidige onderwerp, d.w.z. jokertekens, dit sectie.

Maar kort gezegd, wat je zou kunnen gebruiken is de andere syntaxis van Mockito om te helpen met je huidige situatie:

doReturn(interfaces).when(classAMock).getMyInterfaces();

Of met de BDD-aliassen:

willReturn(interfaces).given(classAMock).getMyInterfaces();

Niettemin zou je wrappers kunnen schrijven die generiek vriendelijker zijn. Dat zal toekomstige ontwikkelaars helpen met dezelfde API van derden te werken.


Als een kanttekening: je moet niet moppen type dat je niet bezit, het kan leiden tot veel fouten en problemen. In plaats daarvan zou je een wikkel moeten hebben. DAO en repositories vertegenwoordigen bijvoorbeeld een dergelijk idee, men zal de DAO- of repository-interface bespotten, maar niet de JDBC / JPA / winterslaap-dingen. Daarover zijn veel blogposts:


55
2018-04-11 09:16



Een andere oplossing (hoewel minder goed leesbaar) is om de statische methode aanroep van when om het jokerteken te binden:

Mockito.<List<? extends MyInterface>>when(classAMock.getMyInterfaces()).thenReturn(interfaces);

38
2017-10-01 14:44