java 单元测试- RestTemplate模拟保持返回空值

rvpgvaaj  于 2022-12-21  发布在  Java
关注(0)|答案(1)|浏览(204)

因此,我正在编写一个进行bankId身份验证的类的单元测试,单元测试如下所示。

package se.kt.client;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpEntity;
import se.kt.common.vo.PublicApplicationForm;
import se.kt.models.BankIdAuthRequest;
import se.kt.models.BankIdAuthResponse;
import se.kt.models.BankIdCollectResponse;
import static org.mockito.ArgumentMatchers.any;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;

@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class BankIdClientTest {

    private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);

    @InjectMocks
    private BankIdClient bankIdClient;

    @BeforeEach
    public void setUp() {
    }


    @Test
    public void testBankIdAuthentication_success() throws InterruptedException {
        PublicApplicationForm form = new PublicApplicationForm();
        form.setSsn("123456-7890");
        form.setIp_address("123.123.123.123");

        BankIdAuthRequest authRequest = bankIdClient.authRequestFromApplicationForm(form, "123");

        BankIdAuthResponse authResponse = new BankIdAuthResponse();
        authResponse.setOrderRef("123456");

        BankIdCollectResponse collectResponse = new BankIdCollectResponse();
        collectResponse.setStatus("completed");

        Mockito.when(restTemplate.postForEntity(anyString(), any(HttpEntity.class), any()))
                .thenReturn(ResponseEntity.ok(authResponse));
        Mockito.when(restTemplate.getForEntity(anyString(), any()))
                .thenReturn(ResponseEntity.ok(collectResponse));

        assertTrue(bankIdClient.bankIdAuthentication(authRequest));
    }
}

Im测试的类如下所示:

package se.kt.client;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import se.kt.common.domain.AbstractApplicationForm;
import se.kt.common.vo.PublicApplicationForm;
import se.kt.models.BankIdAuthRequest;
import se.kt.models.BankIdAuthResponse;
import se.kt.models.BankIdCollectResponse;

import javax.validation.constraints.AssertFalse;
import javax.validation.constraints.AssertTrue;
import java.util.Objects;

@Component
public class BankIdClient {

    private static final Logger log = LoggerFactory.getLogger(BankIdClient.class);
    private final RestTemplate customRestTemplate;
    private static final String CONTENT_TYPE = "Content-Type";

    @Value("${BankId.AuthUrl}")
    private String bankIdAuthUrl;

    @Value("${BankId.CollectUrl}")
    private String bankIdCollectUrl;

    @Value("${BankId.SecretKey}")
    private String bankIdSecretKey;

    public BankIdClient(RestTemplate customRestTemplate) {
        this.customRestTemplate = customRestTemplate;
    }

    public BankIdAuthRequest authRequestFromApplicationForm(PublicApplicationForm form, String jobId) {
        BankIdAuthRequest bankIdAuthRequest = new BankIdAuthRequest();
        bankIdAuthRequest.setPno(form.getSsn());
        bankIdAuthRequest.setIpAddress(form.getIp_address());
        bankIdAuthRequest.setRefID(jobId);
        bankIdAuthRequest.setSecretKey(bankIdSecretKey);
        bankIdAuthRequest.setAvsikt("Kt application");

        return bankIdAuthRequest;
    }

    public boolean bankIdAuthentication(BankIdAuthRequest bankIdAuthRequest) throws InterruptedException {
        //Setup header and body for request.
        HttpHeaders headers = new HttpHeaders();
        headers.add(CONTENT_TYPE, MediaType.APPLICATION_JSON.toString());

        ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();

        try {
            String bankIdAuthFormJson = ow.writeValueAsString(bankIdAuthRequest);

            HttpEntity<String> httpEntity = new HttpEntity<>(bankIdAuthFormJson, headers);
            ResponseEntity<BankIdAuthResponse> authResponse = customRestTemplate.postForEntity(bankIdAuthUrl, httpEntity, BankIdAuthResponse.class);

            bankIdCollectUrl += Objects.requireNonNull(authResponse.getBody()).getOrderRef();

            ResponseEntity<BankIdCollectResponse> collectResponse;

            do {
                collectResponse = customRestTemplate.getForEntity(bankIdCollectUrl, BankIdCollectResponse.class);

                Thread.sleep(1500);

                if (Objects.requireNonNull(collectResponse.getBody()).getStatus().equals("completed"))
                    return true;
                if (Objects.requireNonNull(collectResponse.getBody()).getStatus().equals("failed"))
                    return false;
            } while (Objects.requireNonNull(collectResponse.getBody()).getStatus().equals("progress"));

        } catch (JsonProcessingException e) {
            log.info(e.getMessage());
        } catch (NullPointerException e) {
            log.info(e.toString());
            log.info("BankId API not responding correctly. Check server connection");
        }
        return false;
    }

    public void cancelBankIdAuthentication(@Value("${BankId.CancelUrl}") String bankIdCancelUrl) {
        customRestTemplate.postForEntity(bankIdCancelUrl, null, String.class);
    }
}

下面是这一行的一些原因:

ResponseEntity<BankIdAuthResponse> authResponse = customRestTemplate.postForEntity(bankIdAuthUrl, httpEntity, BankIdAuthResponse.class);

保持产生结果authResponse = null,其指示

Mockito.when(restTemplate.postForEntity(anyString(), any(HttpEntity.class), any()))
                .thenReturn(ResponseEntity.ok(authResponse));

不起作用。现在我已经玩了3个多小时了,我仍然得到同样的结果。我会做错什么呢?

ippsafx7

ippsafx71#

@InjectMocks只适用于@Mock注解的字段,不适用于分配了手动创建的模拟的字段。因此您需要更改:

private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);

@InjectMocks
private BankIdClient bankIdClient;

@Mock
private RestTemplate restTemplate;

@InjectMocks
private BankIdClient bankIdClient;

我还推荐阅读Why is my class not calling my mocked methods in unit test?,它提供了额外的见解,并指出了一般使用Mockito或mock时的一些常见错误。

相关问题