webentwicklung-frage-antwort-db.com.de

Wie mache ich einen Spott? REST Vorlagenaustausch?

Ich habe einen Dienst, in dem ich einen externen Server über rest nach Informationen fragen muss:

public class SomeService {

    public List<ObjectA> getListofObjectsA() {
        List<ObjectA> objectAList = new ArrayList<ObjectA>();
        ParameterizedTypeReference<List<ObjectA>> typeRef = new ParameterizedTypeReference<List<ObjectA>>() {};
        ResponseEntity<List<ObjectA>> responseEntity = restTemplate.exchange("/objects/get-objectA", HttpMethod.POST, new HttpEntity<>(ObjectAList), typeRef);
        return responseEntity.getBody();
    }
}

Wie schreibe ich einen JUnit-Test für getListofObjectsA()?

Ich habe es mit dem folgenden versucht:

@RunWith(MockitoJUnitRunner.class)
public class SomeServiceTest {
    private MockRestServiceServer mockServer;

    @Mock
    private RestTemplate restTemplate;

    @Inject
   private SomeService underTest;

@Before
public void setup() {
    mockServer = MockRestServiceServer.createServer(restTemplate);
    underTest = new SomeService(restTemplate);
    mockServer.expect(requestTo("/objects/get-objectA")).andExpect(method(HttpMethod.POST))
            .andRespond(withSuccess("{json list response}", MediaType.APPLICATION_JSON));
}

    @Test
    public void testGetObjectAList() {
    List<ObjectA> res = underTest.getListofObjectsA();
    Assert.assertEquals(myobjectA, res.get(0));
}

Der obige Code funktioniert jedoch nicht, er zeigt jedoch, dass responseEntittynull ist. Wie kann ich meinen Test korrigieren, um restTemplate.exchange richtig zu verspotten?

17
Akka Jaworek

Sie brauchen kein MockRestServiceServer Objekt. Die Anmerkung lautet @InjectMocks nicht @Inject. Unten ist ein Beispielcode, der funktionieren sollte

@RunWith(MockitoJUnitRunner.class)
public class SomeServiceTest {
    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    private SomeService underTest;

    @Test
    public void testGetObjectAList() {
        ObjectA myobjectA = new ObjectA();
        //define the entity you want the exchange to return
        ResponseEntity<List<ObjectA>> myEntity = new ResponseEntity<List<ObjectA>>(HttpStatus.ACCEPTED);
        Mockito.when(restTemplate.exchange(
            Matchers.eq("/objects/get-objectA"),
            Matchers.eq(HttpMethod.POST),
            Matchers.<HttpEntity<List<ObjectA>>>any(),
            Matchers.<ParameterizedTypeReference<List<ObjectA>>>any())
        ).thenReturn(myEntity);

        List<ObjectA> res = underTest.getListofObjectsA();
        Assert.assertEquals(myobjectA, res.get(0));
    }
17
Mindaugas
ResponseEntity<String> responseEntity = new ResponseEntity<String>("sampleBodyString", HttpStatus.ACCEPTED);
when(restTemplate.exchange(
                           Matchers.anyString(), 
                           Matchers.any(HttpMethod.class),
                           Matchers.<HttpEntity<?>> any(), 
                           Matchers.<Class<String>> any()
                          )
                         ).thenReturn(responseEntity);
14

Dies ist ein Beispiel für die nicht depreated ArgumentMatchers class

when(restTemplate.exchange(
                ArgumentMatchers.anyString(),
                ArgumentMatchers.any(HttpMethod.class),
                ArgumentMatchers.any(),
                ArgumentMatchers.<Class<String>>any()))
             .thenReturn(responseEntity);
8
itstata

Für mich musste ich Matchers.any (URI.class) verwenden. 

Mockito.when(restTemplate.exchange(Matchers.any(URI.class), Matchers.any(HttpMethod.class), Matchers.<HttpEntity<?>> any(), Matchers.<Class<Object>> any())).thenReturn(myEntity);
4
Abbin Varghese

Diese Arbeit auf meiner Seite.

ResourceBean resourceBean = initResourceBean();
ResponseEntity<ResourceBean> responseEntity  
    = new ResponseEntity<ResourceBean>(resourceBean, HttpStatus.ACCEPTED);
when(restTemplate.exchange(
    Matchers.anyObject(), 
    Matchers.any(HttpMethod.class),
    Matchers.<HttpEntity> any(), 
    Matchers.<Class<ResourceBean>> any())
 ).thenReturn(responseEntity);
2
chendu

Die RestTemplate-Instanz muss ein reales Objekt sein. Es sollte funktionieren, wenn Sie eine echte Instanz von RestTemplate erstellen und @Spy erstellen.

@Spy
private RestTemplate restTemplate = new RestTemplate();
0
Manoj Shrestha

Wenn Sie beabsichtigen, den Dienst ohne Rücksicht auf den Rest Call zu testen, schlage ich vor, keine Anmerkungen in Ihrem Gerätetest zu verwenden, um den Test zu vereinfachen.

Mein Vorschlag ist also die Umgestaltung Ihres Dienstes, um die Vorlage mithilfe des Injektionskonstruktors zu erhalten. Dies erleichtert den Test. Beispiel:

@Service
class SomeService {
    @AutoWired
    SomeService(TestTemplateObjects restTemplateObjects) {
        this.restTemplateObjects = restTemplateObjects;
    }
}

Die RestTemplate als Komponente, nach der injiziert und verspottet werden soll:

@Component
public class RestTemplateObjects {

    private final RestTemplate restTemplate;

    public RestTemplateObjects () {
        this.restTemplate = new RestTemplate();
        // you can add extra setup the restTemplate here, like errorHandler or converters
    }

    public RestTemplate getRestTemplate() {
        return restTemplate;
    }
}

Und der Test:

public void test() {

    when(mockedRestTemplateObject.get).thenReturn(mockRestTemplate);

    //mock restTemplate.exchange
    when(mockRestTemplate.exchange(...)).thenReturn(mockedResponseEntity);

    SomeService someService = new SomeService(mockedRestTemplateObject);
    someService.getListofObjectsA();
}

Auf diese Weise haben Sie direkten Zugriff auf die Restvorlage durch den SomeService-Konstruktor.

0
Dherik

Wenn Sie RestTemplateBuilder verwenden, funktioniert möglicherweise das Übliche nicht. Sie müssen dies in Ihrer Testklasse zusammen mit dem Zeitpunkt (Bedingung) hinzufügen.

@Before    
public void setup() {        
     ReflectionTestUtils.setField(service, "restTemplate", restTemplate);    
}
0
Debiprasad

Ich habe eine kleine Bibliothek implementiert das ist sehr nützlich. Es stellt eine ClientHttpRequestFactory bereit, die einen Kontext erhalten kann. Auf diese Weise können Sie alle Clientebenen durchgehen, indem Sie prüfen, ob die Abfrageparameter bewertet, die Header festgelegt und die Deserialisierung ordnungsgemäß funktioniert.

0
Kier GRAY