package com.tourguide.integration.wechat;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.tourguide.common.exception.BusinessException;
|
import com.tourguide.config.properties.WechatMiniProgramProperties;
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.ValueOperations;
|
import org.springframework.http.MediaType;
|
import org.springframework.test.web.client.MockRestServiceServer;
|
import org.springframework.web.client.RestTemplate;
|
|
import java.time.Duration;
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
|
class WechatMiniProgramClientTest {
|
private StringRedisTemplate redisTemplate;
|
private ValueOperations<String, String> valueOperations;
|
private MockRestServiceServer server;
|
private WechatMiniProgramClient client;
|
|
@BeforeEach
|
@SuppressWarnings("unchecked")
|
void setUp() {
|
RestTemplate restTemplate = new RestTemplate();
|
server = MockRestServiceServer.bindTo(restTemplate).build();
|
redisTemplate = mock(StringRedisTemplate.class);
|
valueOperations = mock(ValueOperations.class);
|
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
|
when(valueOperations.get(anyString())).thenReturn(null);
|
|
WechatMiniProgramProperties properties = new WechatMiniProgramProperties();
|
properties.setAppId("test-app");
|
properties.setAppSecret("test-secret");
|
client = new WechatMiniProgramClient(properties, restTemplate, redisTemplate, new ObjectMapper());
|
}
|
|
@Test
|
void shouldExchangeLoginAndPhoneCodes() {
|
server.expect(requestTo("https://api.weixin.qq.com/sns/jscode2session?appid=test-app&secret=test-secret&js_code=login-code&grant_type=authorization_code"))
|
.andRespond(withSuccess("{\"openid\":\"openid-1\",\"session_key\":\"session-key\"}", MediaType.TEXT_PLAIN));
|
server.expect(requestTo("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=test-app&secret=test-secret"))
|
.andRespond(withSuccess("{\"access_token\":\"access-token\",\"expires_in\":7200}", MediaType.TEXT_PLAIN));
|
server.expect(requestTo("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=access-token"))
|
.andExpect(content().json("{\"code\":\"phone-code\"}"))
|
.andRespond(withSuccess("{\"errcode\":0,\"errmsg\":\"ok\",\"phone_info\":{\"purePhoneNumber\":\"13800138000\"}}", MediaType.TEXT_PLAIN));
|
|
WechatPhoneAuthorization authorization = client.authorizePhoneLogin("login-code", "phone-code");
|
|
assertThat(authorization.getOpenid()).isEqualTo("openid-1");
|
assertThat(authorization.getMobile()).isEqualTo("13800138000");
|
verify(valueOperations).set("tourguide:wechat:mini:access-token:test-app", "access-token", Duration.ofSeconds(6900));
|
server.verify();
|
}
|
|
@Test
|
void shouldReportWechatConfigurationError() {
|
server.expect(requestTo("https://api.weixin.qq.com/sns/jscode2session?appid=test-app&secret=test-secret&js_code=login-code&grant_type=authorization_code"))
|
.andRespond(withSuccess("{\"errcode\":40125,\"errmsg\":\"invalid appsecret\"}", MediaType.TEXT_PLAIN));
|
|
assertThatThrownBy(() -> client.authorizePhoneLogin("login-code", "phone-code"))
|
.isInstanceOf(BusinessException.class)
|
.hasMessage("微信小程序 AppID 或 AppSecret 配置错误(微信错误码:40125)");
|
server.verify();
|
}
|
}
|