无法使用 Mockito 在 Spring 引导中模拟 AWSSecretsManager
Unable to mock AWSSecretsManager in Spring boot using Mockito
我是 Java 的新手,我已经创建了示例 class,我需要为其编写单元测试用例
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
import com.amazonaws.services.secretsmanager.model.GetSecretValueResult;
import com.amazonaws.services.secretsmanager.model.InvalidParameterException;
import com.amazonaws.services.secretsmanager.model.ResourceNotFoundException;
import org.springframework.stereotype.Component;
@Component
public class MySecretService {
private AWSSecretsManager client;
public MySecretService() {
this.client = AWSSecretsManagerClientBuilder.standard().withRegion("US-west-2").build();
}
public String GetMyKey(String secretId) {
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest();
getSecretValueRequest.setSecretId(secretId);
try {
GetSecretValueResult getSecretValueResult = client.getSecretValue(getSecretValueRequest);
return getSecretValueResult.getSecretString();
} catch (ResourceNotFoundException resourceNotFoundException) {
throw resourceNotFoundException;
} catch (InvalidParameterException invalidParameterException) {
throw invalidParameterException;
}
catch (Exception ex)
{
throw ex;
}
}
}
我尝试编写如下单元测试用例
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
import com.amazonaws.services.secretsmanager.model.GetSecretValueResult;
import com.amazonaws.services.secretsmanager.model.ResourceNotFoundException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
class MySecretServiceTest {
@Mock
private AWSSecretsManager client;
private MySecretService mySecretService;
@BeforeEach
void setUp() {
this.mySecretService = new MySecretService();
}
@Test
void getMyKey() {
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest();
getSecretValueRequest.setSecretId("test");
GetSecretValueResult getSecretValueResult = new GetSecretValueResult();
getSecretValueResult.setSecretString("xyz");
when(this.client.getSecretValue(getSecretValueRequest))
.thenReturn( getSecretValueResult);
assertEquals("xyz", mySecretService.GetMyKey("test"));
}
}
但是我的测试失败了,它说 AWSSecretsManager 为 null 并出现以下错误。
java.lang.NullPointerException
在 com.example.demo.MySecretServiceTest.getMyKey(MySecretServiceTest.java:40)
我尝试了不同的解决方案,但无法帮助我成功执行测试用例。
我认为你是如何构建代码的,这使得注入 AWSSecretsManager
客户端变得非常困难。这是因为它没有作为 MySecretService
服务中的依赖项公开。
我建议做的是:
- 创建配置 class 并将
AWSSecretsManager
的实例放入 IoC 容器中:
@Configuration
public class AWSConfig {
@Bean
public AWSSecretsManager awsSecretsManager() {
return AWSSecretsManagerClientBuilder.standard()
.withRegion("us-east-1")
.build();
}
}
- 在您的服务中注入
AWSSecretsManager
的 bean:
@Service
public class MySecretService {
private final AWSSecretsManager awsSecretsManager;
public SecretsService(AWSSecretsManager awsSecretsManager) {
this.awsSecretsManager = awsSecretsManager;
}
public String getMyKey(String secretId) {
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest().withSecretId(secretId);
try {
GetSecretValueResult getSecretValueResult = awsSecretsManager.getSecretValue(getSecretValueRequest);
return getSecretValueResult.getSecretString();
} catch (ResourceNotFoundException | InvalidParameterException resourceNotFoundException) {
throw resourceNotFoundException;
}
}
}
- 现在,在您的测试中,我发现您正在混合使用 JUnit 4 和 Junit 5 依赖项,这不是一个好主意。最新的 Spring 用于测试的引导启动程序随 JUnit 5 一起提供,我建议坚持使用它。知道了这一点,我们可以做到以下几点:
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
import com.amazonaws.services.secretsmanager.model.GetSecretValueResult;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class MySecretServiceTest {
@Mock
private AWSSecretsManager client;
@InjectMocks
private SecretsService mySecretService;
@Test
void getMyKey() {
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest();
getSecretValueRequest.setSecretId("test");
GetSecretValueResult getSecretValueResult = new GetSecretValueResult();
getSecretValueResult.setSecretString("xyz");
when(client.getSecretValue(getSecretValueRequest))
.thenReturn(getSecretValueResult);
assertEquals("xyz", mySecretService.GetMyKey("test"));
}
}
我是 Java 的新手,我已经创建了示例 class,我需要为其编写单元测试用例
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
import com.amazonaws.services.secretsmanager.model.GetSecretValueResult;
import com.amazonaws.services.secretsmanager.model.InvalidParameterException;
import com.amazonaws.services.secretsmanager.model.ResourceNotFoundException;
import org.springframework.stereotype.Component;
@Component
public class MySecretService {
private AWSSecretsManager client;
public MySecretService() {
this.client = AWSSecretsManagerClientBuilder.standard().withRegion("US-west-2").build();
}
public String GetMyKey(String secretId) {
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest();
getSecretValueRequest.setSecretId(secretId);
try {
GetSecretValueResult getSecretValueResult = client.getSecretValue(getSecretValueRequest);
return getSecretValueResult.getSecretString();
} catch (ResourceNotFoundException resourceNotFoundException) {
throw resourceNotFoundException;
} catch (InvalidParameterException invalidParameterException) {
throw invalidParameterException;
}
catch (Exception ex)
{
throw ex;
}
}
}
我尝试编写如下单元测试用例
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
import com.amazonaws.services.secretsmanager.model.GetSecretValueResult;
import com.amazonaws.services.secretsmanager.model.ResourceNotFoundException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
class MySecretServiceTest {
@Mock
private AWSSecretsManager client;
private MySecretService mySecretService;
@BeforeEach
void setUp() {
this.mySecretService = new MySecretService();
}
@Test
void getMyKey() {
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest();
getSecretValueRequest.setSecretId("test");
GetSecretValueResult getSecretValueResult = new GetSecretValueResult();
getSecretValueResult.setSecretString("xyz");
when(this.client.getSecretValue(getSecretValueRequest))
.thenReturn( getSecretValueResult);
assertEquals("xyz", mySecretService.GetMyKey("test"));
}
}
但是我的测试失败了,它说 AWSSecretsManager 为 null 并出现以下错误。
java.lang.NullPointerException 在 com.example.demo.MySecretServiceTest.getMyKey(MySecretServiceTest.java:40)
我尝试了不同的解决方案,但无法帮助我成功执行测试用例。
我认为你是如何构建代码的,这使得注入 AWSSecretsManager
客户端变得非常困难。这是因为它没有作为 MySecretService
服务中的依赖项公开。
我建议做的是:
- 创建配置 class 并将
AWSSecretsManager
的实例放入 IoC 容器中:
@Configuration
public class AWSConfig {
@Bean
public AWSSecretsManager awsSecretsManager() {
return AWSSecretsManagerClientBuilder.standard()
.withRegion("us-east-1")
.build();
}
}
- 在您的服务中注入
AWSSecretsManager
的 bean:
@Service
public class MySecretService {
private final AWSSecretsManager awsSecretsManager;
public SecretsService(AWSSecretsManager awsSecretsManager) {
this.awsSecretsManager = awsSecretsManager;
}
public String getMyKey(String secretId) {
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest().withSecretId(secretId);
try {
GetSecretValueResult getSecretValueResult = awsSecretsManager.getSecretValue(getSecretValueRequest);
return getSecretValueResult.getSecretString();
} catch (ResourceNotFoundException | InvalidParameterException resourceNotFoundException) {
throw resourceNotFoundException;
}
}
}
- 现在,在您的测试中,我发现您正在混合使用 JUnit 4 和 Junit 5 依赖项,这不是一个好主意。最新的 Spring 用于测试的引导启动程序随 JUnit 5 一起提供,我建议坚持使用它。知道了这一点,我们可以做到以下几点:
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
import com.amazonaws.services.secretsmanager.model.GetSecretValueResult;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class MySecretServiceTest {
@Mock
private AWSSecretsManager client;
@InjectMocks
private SecretsService mySecretService;
@Test
void getMyKey() {
GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest();
getSecretValueRequest.setSecretId("test");
GetSecretValueResult getSecretValueResult = new GetSecretValueResult();
getSecretValueResult.setSecretString("xyz");
when(client.getSecretValue(getSecretValueRequest))
.thenReturn(getSecretValueResult);
assertEquals("xyz", mySecretService.GetMyKey("test"));
}
}