如何解决如何使用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 举报,一经查实,本站将立刻删除。