I am new to Java and I have created sample class for which I need to write unit test case
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;
}
}
}
I tried to write unit test case as below
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"));
}
}
However my test is getting failed where it says AWSSecretsManager is null with below error.
java.lang.NullPointerException at com.example.demo.MySecretServiceTest.getMyKey(MySecretServiceTest.java:40)
I tried different solution but won't help me to execute the test cases successfully.
CodePudding user response:
I think that way how did you structure your code, you make it really hard to inject AWSSecretsManager
client. This is because it is not exposed as a dependency in the MySecretService
service.
What I suggest doing is the following:
- Create a configuration class and put an instance for
AWSSecretsManager
in the IoC container:
@Configuration
public class AWSConfig {
@Bean
public AWSSecretsManager awsSecretsManager() {
return AWSSecretsManagerClientBuilder.standard()
.withRegion("us-east-1")
.build();
}
}
- Inject the bean of
AWSSecretsManager
inside your service:
@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;
}
}
}
- Now, in your test I see that you are mixing JUnit 4 and Junit 5 dependencies, which is not a good idea. The latest Spring Boot starter for testing comes with JUnit 5, I suggest sticking to it. Knowing this, we can do the following:
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"));
}
}