web-dev-qa-db-fra.com

Comment se moquer de RestTemplate dans Java Spring?

public class ServiceTest {
    @Mock
    RestTemplate restTemplate = new RestTemplate();
    @InjectMocks
    Service service = new Service();
    ResponseEntity responseEntity = mock(ResponseEntity.class);

    @Test
    public void test() throws Exception {
        Mockito.when(restTemplate.getForEntity(
                Mockito.anyString(),
                Matchers.any(Class.class)
                ))
                .thenReturn(responseEntity);
        boolean res = service.isEnabled("something");
        Assert.assertEquals(res, false);
    }

J'ai essayé de tester un test simple pour un service incluant un restclient. Il semble que je n’ai pas moqué la RestTemplate avec succès. Il semble que le code obtienne les données réelles et non les données factices. Tout le monde peut m'aider avec ça.

Le service lui-même ressemblera à ceci:

public class Service{
    public boolean isEnabled(String xxx) {
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.getForEntity("someurl",String.class);
        if(...)return true;
        return false;
    }
}
13
c2340878

Le problème est que dans votre isEnabled, vous créez un nouveau RestTemplate. Cela est faux pour deux raisons. La première est que vous ne pouvez pas vous moquer de cette carte puisque vous en créez une nouvelle. Deuxièmement, il est bon d'éviter de créer de nouveaux objets par requête. RestTemplate est thread-safe et peut donc être un membre de la classe de service, utilisé par plusieurs threads.

Changez votre classe de service en quelque chose comme ceci:

public class Service{

    RestTemplate restTemplate = new RestTemplate();

    public boolean isEnabled(String xxx) {
        ResponseEntity<String> response = restTemplate.getForEntity("someurl",String.class);
        if(...)return true;
        return false;
    }
}

Maintenant que votre RestTemplate est devenu un membre du groupe, vous pouvez maintenant vous moquer de l'une des deux manières suivantes. Tout d'abord, injectez-le à l'aide du @InjectMock ou utilisez une méthode de définition que vous appelez à partir de votre test.

Puisque vous utilisez InjectMock dans votre code, nous pouvons continuer avec cela.

@RunWith(MockitoJUnitRunner.class) 
public class ServiceTest {
    @Mock
    RestTemplate restTemplate;
    @InjectMocks
    @Spy
    Service service;
    ResponseEntity responseEntity = mock(ResponseEntity.class);

    @Test
    public void test() throws Exception {
        Mockito.when(restTemplate.getForEntity(
                Mockito.anyString(),
                ArgumentMatchers.any(Class.class)
                ))
                .thenReturn(responseEntity);
        boolean res = service.isEnabled("something");
        Assert.assertEquals(res, false);
    }

Notez que j'ai fait quelques changements. Premièrement, j'ai supprimé les new RestTemplate() et new Service(). Vous devriez laisser Mockito les créer pour vous. En les annotant avec @Mock et @Spy, vous vous assurerez que Mockito les créera pour vous et, plus important encore, injectera les imitations dans votre objet service.

19
Jose Martinez

La structure de test de Spring MVC propose la classe MockRestServiceServer pour le code de service RESTful des tests unitaires. 

Voici un tutorial sur son utilisation.

7
Keith

Si vous utilisez @Autowired, vous pouvez utiliser MockRestServiceServer . L'exemple ci-dessous est l'exemple.

@Service
public class Service{
    @Autowired
    private RestTemplate restTemplate;

    public boolean isEnabled(String xxx) {
        ResponseEntity<String> response = restTemplate.getForEntity("someurl",String.class);
        if(...)return true;
        return false;
    }
}

@Service doit utiliser @Autowired pour créer un objet automatiquement.

0
hiroyukik