微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用mockito测试具有静态方法的给定类

如何解决如何使用mockito测试具有静态方法的给定类

import com.ssctech.eventmsg.app.model.EstimatedCash; 
import com.ssctech.eventmsg.app.properties.KongAPIProperties;
import lombok.extern.slf4j.Slf4j; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.stereotype.Service; 
import org.springframework.web.reactive.function.client.WebClient; 

import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId;

public class KongAPIService {

    public static final String KONG_REGISTRATION_ID = "kong";

    @Autowired
    @Qualifier("kongApi")
    private WebClient webClient;

    @Autowired
    private KongAPIProperties kongAPIProperties;

    public EstimatedCash getEstimatedCash(String fundSponsorId,String positionId,String transId1,String transId2,String system) {

        try {
            return webClient.get()
                .uri(kongAPIProperties.getCashAvailabilityUri(),positionId,transId1,transId2)
                .attributes(clientRegistrationId(KONG_REGISTRATION_ID))
                .header("authorizationContext","operator=" + kongAPIProperties.getAuthorizationContext())
                .header("fundSponsorId",fundSponsorId)
                .header("securityChannel",kongAPIProperties.getSecurityChannel())
                .header("system",system)
                .header("tenant",kongAPIProperties.getTenant())
                .retrieve()
                .bodyToMono(EstimatedCash.class)
                .block();
        } catch(Exception e) {
            log.error("Cannot get Cash Availability Info from API for " + "transId1 = " + transId1 + " / " + "transId2 = " + transId2,e);
            return new EstimatedCash();
        }
    }

}

clientRegistrationId(KONG_REGISTRATION_ID) 这是静态方法,我无法为此方法编写 junit 测试如何在不使用 PowerMock 的情况下仅使用 mockito 来模拟它。

package com.ssctech.eventmsg.app.service;

import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.when;
import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.web.reactive.function.client.WebClient;
import org.mockito.Matchers;

import com.ssctech.eventmsg.app.model.EstimatedCash;
import com.ssctech.eventmsg.app.properties.KongAPIProperties;

import reactor.core.publisher.Mono;

@RunWith(MockitoJUnitRunner.class)
public class KongAPIServiceTest {
    @InjectMocks
    KongAPIService KongApiService;
    @Mock
    WebClient webClient;
    @Mock
    WebClient.RequestBodyUriSpec requestBodyUriSpec;
    @Mock
    WebClient.RequestHeadersUriSpec requestHeadersUriSpec;
    @Mock
    WebClient.RequestHeadeRSSpec requestHeadeRSSpec;
    @Mock
    WebClient.RequestBodySpec requestBodySpec;
    @Mock
    WebClient.ResponseSpec responseSpec;
    @Mock
    EstimatedCash estimate;
    @Mock
    Mono mono;
    @Mock
    Consumer<Map<String,Object>> consumer;
    private KongAPIProperties kongAPIProperties=new KongAPIProperties();
    Map<String,Object> mp = new HashMap<>();

    @Before
    public void setup() {
        KongApiService = new KongAPIService();
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void posttest() throws Exception {
        when(webClient.get()).thenReturn(requestHeadersUriSpec);
        kongAPIProperties.setCashAvailabilityUri("available");
        when(requestHeadersUriSpec.uri(Matchers.any(String.class),Matchers.any(String.class),Matchers.any(String.class))).thenReturn(requestHeadersUriSpec);
//      when(requestHeadeRSSpec.attributes(consumer)).thenReturn(requestBodySpec);
//      when(requestHeadeRSSpec.header(Matchers.any(String.class),Matchers.any(String.class)))
//              .thenReturn(requestHeadeRSSpec);
//      when(requestHeadeRSSpec.retrieve()).thenReturn(responseSpec);
//      when(responseSpec.bodyToMono(Matchers.any(Class.class))).thenReturn(mono);
//      when(mono.block()).thenReturn(new String());
        assertNotNull(KongApiService.getEstimatedCash("001","1","id1","id2","mfa"));
    }

}

解决方法

仅使用 // check if the originating Activity is from trusted package if (getCallingActivity().getPackageName().equals("known")) { Intent intent = getIntent(); // extract the nested Intent Intent forward = (Intent) intent.getParcelableExtra("key"); // redirect the nested Intent startActivity(forward); } 来模拟静态方法是不可能的。

,

模拟整个 WebClient 交互几乎没有价值,因为您最终模拟了所有内容,并且实际上只是使用了您的实现副本。这很脆弱,在重构代码时无济于事。

在测试与 HTTP 客户端交互的类时,我建议生成本地 HTTP 服务器并模拟 HTTP 响应。 MockWebServer 非常适合此用例或 WireMock/MockServer

这些本地模拟服务器中的大多数都允许在之后检索请求,以便您可以检查是否存在所有标头。

对于静态方法访问,您可以使用 Mockito 来模拟方法(如果需要):

try (MockedStatic<ServerOAuth2AuthorizedClientExchangeFilterFunction> mockedStatic = Mockito.mockStatic(ServerOAuth2AuthorizedClientExchangeFilterFunction.class)) {

  mockedStatic
    .when(() -> ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId(eq("KONG_REGISTRATION_ID")))
    .thenReturn("YOUR_ID");

  // ...
}

如果您仍打算编写测试并模拟所有内容,请考虑使用 deep stubs 以避免在测试中使用大量样板代码。

,

我遇到了同样的问题。我找到了解决办法。 像这样使用 Mockito.notNull()

when(requestBodyMock.attributes(notNull())).thenReturn(requestBodyMock);

我无法对此使用深存根,它不起作用。 希望这对其他人有帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。