模拟对象返回null

时间:2020-01-10 14:11:46

标签: java junit mocking mockito

JUnit测试类:

public class TestingClass {

    @Mock
    private RestTemplate restTemplate;

    @Mock
    private HttpEntity entity;

    @Mock
    private ResponseEntity<Resource> responseEntity;

    @Before
    public void setup() {

        MockitoHelper.initMocks(this);

    }

    @Test
    public void getDataTest() {

        ClassToTest c = new ClassToTest(restTemplate);

        when(restTemplate.exchange("http://testing", HttpMethod.GET, entity, Resource.class)).thenReturn(responseEntity);
        c.getData("http://testing");

    }

}

正在测试的课程:

import org.jsoup.helper.Validate;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import java.io.InputStream;
import java.util.Optional;

public class ClassToTest {

    private HttpHeaders headers;
    private RestTemplate restTemplate;

    public ClassToTest(RestTemplate restTemplate){
        this.restTemplate = restTemplate;
        headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
    }

    public Optional<InputStream> getData(final String mediaUrl) {

        Validate.notEmpty(mediaUrl);

        final String requestJson = "{}";
        final HttpEntity<String> entity = new HttpEntity<>(requestJson, headers);
        Optional inputStreamOptional = Optional.empty();

        try {
            final ResponseEntity<Resource> responseEntity = restTemplate.exchange(mediaUrl, HttpMethod.GET, entity, Resource.class);
            System.out.println(responseEntity);
        } catch (Exception exception) {
            exception.printStackTrace();
        }

        return inputStreamOptional;
    }
}

System.out.println(responseEntity);的结果为null

应将responseEntity设置为其模拟值并按照when(restTemplate.exchange("http://testing", HttpMethod.GET, entity, Resource.class)).thenReturn(responseEntity);

中的配置返回(而不是返回返回null的当前行为)

因此,当调用c.getData("http://testing");时,将返回模拟的responseEntity吗?

改为使用:

when(restTemplate.exchange(Matchers.eq("http://testing"), Matchers.eq(HttpMethod.GET), Matchers.isA(HttpEntity.class), Matchers.eq(Resource.class))).thenReturn(responseEntity);

3 个答案:

答案 0 :(得分:2)

最有可能返回null,因为您在when中的参数定义和实际参数不同。在您的情况下,很有可能您在测试代码中创建的模拟entityHttpEntity既不相同也不相等。因此,您需要扩大对when定义的期望。您应该在定义中使用Matchers,并且对于实体可以使用isA(HttpEntity.class)

答案 1 :(得分:1)

我认为您不需要模拟ResponseEntity,因为ResponseEntity不是要注入的实体。您嘲笑了ResponseEntity,然后再也没有嘲笑它的任何方法,这就是为什么它的null

您需要模拟RestTemplate,然后模拟其:

when(restTemplate.exchange("http://testing", HttpMethod.GET, entity, Resource.class)).thenReturn(responseEntity);

答案 2 :(得分:1)

问题集中在测试中的这一行:

when(restTemplate.exchange("http://testing", HttpMethod.GET, entity, Resource.class)).thenReturn(responseEntity);

这是当您使用这些特定于 参数调用restTemplate.exchange时返回模拟响应实体。请注意,这些参数之一是您的模拟实体。但是,在您的ClassToTest中,该模拟实体不是传递给restTemplate.exchange的实体。因此,在运行测试时,您永远都不会碰到存根期望的确切方法签名。

尝试以下方法:

when(restTemplate.exchange(eq("http://testing"), eq(HttpMethod.GET), any(HttpEntity.class), eq(Resource.class))).thenReturn(responseEntity);

这将用匹配器替换特定的参数,并使您的存根方法在 any HttpEntity而不是特定的模拟对象上触发。

请注意,如果您根本不使用任何匹配器,则必须对 all 参数使用匹配器,这就是eq()方法的作用。