You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
4.7 KiB
83 lines
4.7 KiB
package com.mydreamjob.auth.sms;
|
|
|
|
import com.aliyun.dysmsapi20170525.Client;
|
|
import com.aliyun.dysmsapi20170525.models.*;
|
|
import com.aliyun.teautil.models.RuntimeOptions;
|
|
import com.mydreamjob.common.exception.BusinessException;
|
|
import com.mydreamjob.common.exception.ErrorCode;
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.mockito.ArgumentCaptor;
|
|
import static org.assertj.core.api.Assertions.*;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.Mockito.*;
|
|
|
|
class AliyunSmsCodeSenderTest {
|
|
private Client client;
|
|
private AliyunSmsCodeSender sender;
|
|
private static final String PHONE="19900009890", CODE="652901";
|
|
@BeforeEach void setup() {
|
|
client=mock(Client.class);
|
|
var config=new AliyunSmsProperties();
|
|
config.setAccessKeyId("test-key-not-real"); config.setAccessKeySecret("test-secret-not-real");
|
|
config.setSignName("测试签名"); config.setTemplateCode("SMS_TEST_ONLY");
|
|
sender=new AliyunSmsCodeSender(client,config);
|
|
}
|
|
private SendSmsResponse response(int http,String code) {
|
|
return new SendSmsResponse().setStatusCode(http).setBody(new SendSmsResponseBody().setCode(code));
|
|
}
|
|
@Test void acceptedRequestUsesApprovedSignAndTemplateAndNeverRetries() throws Exception {
|
|
when(client.sendSmsWithOptions(any(),any())).thenReturn(response(200,"OK"));
|
|
sender.sendVerificationCode(PHONE,"login",CODE);
|
|
var req=ArgumentCaptor.forClass(SendSmsRequest.class);
|
|
var runtime=ArgumentCaptor.forClass(RuntimeOptions.class);
|
|
verify(client,times(1)).sendSmsWithOptions(req.capture(),runtime.capture());
|
|
assertThat(req.getValue().getPhoneNumbers()).isEqualTo(PHONE);
|
|
assertThat(req.getValue().getSignName()).isEqualTo("测试签名");
|
|
assertThat(req.getValue().getTemplateCode()).isEqualTo("SMS_TEST_ONLY");
|
|
assertThat(req.getValue().getTemplateParam()).isEqualTo("{\"code\":\"652901\"}");
|
|
assertThat(runtime.getValue().getAutoretry()).isFalse();
|
|
assertThat(runtime.getValue().getConnectTimeout()).isEqualTo(3000);
|
|
assertThat(runtime.getValue().getReadTimeout()).isEqualTo(5000);
|
|
}
|
|
@Test void eachExistingPurposeCanSend() throws Exception {
|
|
when(client.sendSmsWithOptions(any(),any())).thenReturn(response(200,"OK"));
|
|
for(String purpose:new String[]{"login","password-set","password-reset","company-register"})
|
|
sender.sendVerificationCode(PHONE,purpose,CODE);
|
|
verify(client,times(4)).sendSmsWithOptions(any(),any());
|
|
}
|
|
@Test void providerBusinessRejectionNeverReturnsSuccess() throws Exception {
|
|
when(client.sendSmsWithOptions(any(),any())).thenReturn(response(200,"isv.BUSINESS_LIMIT_CONTROL"));
|
|
assertSafeFailure();
|
|
}
|
|
@Test void httpFailureEvenWithOkIsRejected() throws Exception {
|
|
when(client.sendSmsWithOptions(any(),any())).thenReturn(response(500,"OK")); assertSafeFailure();
|
|
}
|
|
@Test void emptyResponseIsRejected() throws Exception {
|
|
when(client.sendSmsWithOptions(any(),any())).thenReturn(null); assertSafeFailure();
|
|
}
|
|
@Test void emptyBodyIsRejected() throws Exception {
|
|
when(client.sendSmsWithOptions(any(),any())).thenReturn(new SendSmsResponse().setStatusCode(200)); assertSafeFailure();
|
|
}
|
|
@Test void missingStatusIsRejected() throws Exception {
|
|
when(client.sendSmsWithOptions(any(),any())).thenReturn(new SendSmsResponse().setBody(new SendSmsResponseBody().setCode("OK"))); assertSafeFailure();
|
|
}
|
|
@Test void exceptionContainingSecretsIsDiscardedAndNotRetried() throws Exception {
|
|
when(client.sendSmsWithOptions(any(),any())).thenThrow(new java.net.SocketTimeoutException(PHONE+CODE+"test-secret-not-real"));
|
|
assertSafeFailure(); verify(client,times(1)).sendSmsWithOptions(any(),any());
|
|
}
|
|
@Test void invalidInputsNeverCallProvider() {
|
|
for(String[] args:new String[][]{{null,"login",CODE},{"bad","login",CODE},{PHONE,null,CODE},
|
|
{PHONE,"anything",CODE},{PHONE,"login",null},{PHONE,"login","1234"},{PHONE,"login","\"malicious"}}) {
|
|
assertThatThrownBy(()->sender.sendVerificationCode(args[0],args[1],args[2])).isInstanceOf(BusinessException.class);
|
|
}
|
|
verifyNoInteractions(client);
|
|
}
|
|
private void assertSafeFailure() {
|
|
assertThatThrownBy(()->sender.sendVerificationCode(PHONE,"login",CODE)).isInstanceOf(BusinessException.class)
|
|
.satisfies(error->{
|
|
assertThat(((BusinessException)error).getErrorCodeInt()).isEqualTo(ErrorCode.SMS_SEND_FAILED.getCode());
|
|
assertThat(error).hasNoCause().hasMessage("sms send failed");
|
|
});
|
|
}
|
|
}
|
|
|