#java #amazon-web-services #amazon-dynamodb #aws-sdk
Вопрос:
У меня есть класс, который сканирует столбец из таблицы базы данных dynamo, используя при этом aws sdk для java(основной метод, взятый для простоты):
public class fetchCmdbColumn {
public static List<String> CMDB(String tableName, String tableColumn) throws Exception {
DynamoDbClient client = DynamoDbClient.builder()
.region(Region.EU_WEST_1)
.build();
List<String> ListValues = new ArrayList<>();
try {
ScanRequest scanRequest = ScanRequest.builder()
.tableName(tableName)
.build();
ScanResponse response = client.scan(scanRequest);
for (Map<String, AttributeValue> item : response.items()){
Set<String> keys = item.keySet();
for (String key : keys) {
if (key == tableColumn) {
ListValues.add(item.get(key).s()) ;
}
}
}
//To check what is being returned, comment out below
// System.out.println(ListValues);
} catch (DynamoDbException e){
e.printStackTrace();
System.exit(1);
}
client.close();
return ListValues;
}
}
У меня также есть тесты junit, созданные для этого класса:
public class fetchCMDBTest {
// Define the data members required for the test
private static String tableName = "";
private static String tableColumn = "";
@BeforeAll
public static void setUp() throws IOException {
// Run tests on Real AWS Resources
try (InputStream input = fetchCMDBTest.class.getClassLoader().getResourceAsStream("config.properties")) {
Properties prop = new Properties();
if (input == null) {
System.out.println("Sorry, unable to find config.properties");
return;
}
//load a properties file from class path, inside static method
prop.load(input);
// Populate the data members required for all tests
tableName = prop.getProperty("environment_list");
tableColumn = prop.getProperty("env_name");
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Test
void fetchCMDBtable() throws Exception{
try {
fetchCMDB.CMDB(tableName, tableColumn);
System.out.println("Test 1 passed");
} catch (Exception e) {
System.out.println("Test 1 failed!");
e.printStackTrace();
}
}
}
Когда я запускаю тест с помощью mvn-теста, я получаю ошибку:
software.amazon.awssdk.core.exception.SdkClientException: Multiple HTTP implementations were found on the classpath
,
даже несмотря на то, что я только один раз объявил построителя клиентов в классе.
Что я упускаю?
Комментарии:
1. Почему вы пытаетесь выполнить модульные тесты для реальной базы данных? Я не думаю, что вам нужно это делать, если только вам не нужно провести какое-то интеграционное тестирование. Если последнее не является вашей целью, то просто издевайтесь над клиентом базы данных и тестируйте свой код с помощью насмешек.
Ответ №1:
Я запускаю модульные тесты из среды разработки IntelliJ. Я нахожу, что использование IDE работает лучше, чем из командной строки. Как только я настрою файл config.properties, содержащий значения для тестов, и запущу их, все тесты пройдут, как показано здесь:
На самом деле — мы тестируем все примеры кода Java V2 таким образом, чтобы убедиться, что все они работают.
Я также протестировал все примеры DynamoDB из командной строки с помощью теста mvn . Все прошло:
Измените свой тест, чтобы создать один экземпляр клиента DynamoDB, а затем в качестве первого теста убедитесь, что он был успешно создан. Посмотрим, сработает ли это для вас. Как только у вас это заработает, добавьте дополнительные тесты!
public class DynamoDBTest {
private static DynamoDbClient ddb;
@BeforeAll
public static void setUp() throws IOException {
// Run tests on Real AWS Resources
Region region = Region.US_WEST_2;
ddb = DynamoDbClient.builder().region(region).build();
try (InputStream input = DynamoDBTest.class.getClassLoader().getResourceAsStream("config.properties")) {
Properties prop = new Properties();
if (input == null) {
System.out.println("Sorry, unable to find config.properties");
return;
}
//load a properties file from class path, inside static method
prop.load(input);
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Test
@Order(1)
public void whenInitializingAWSService_thenNotNull() {
assertNotNull(ddb);
System.out.println("Test 1 passed");
}
Комментарии:
1. я вроде как должен использовать vscode для этого
2. Я также обновлю свой ответ, чтобы показать использование командной строки. Я использую тест mvn, и все тесты пройдены. Смотрите снимок экрана.
3. Если у вас все еще есть проблемы — свяжитесь со мной по ссылке (см. Профиль), и я помогу вам запустить их.
Ответ №2:
Оказывается, в моем файле pom содержались другие клиенты, поэтому пришлось удалить подобные :
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<exclusions>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
</exclusion>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</exclusion>
</exclusions>
</dependency>
и заменил их на :
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>aws-crt-client</artifactId>
<version>2.14.13-PREVIEW</version>
</dependency>
как упоминалось в https://aws.amazon.com/blogs/developer/introducing-aws-common-runtime-http-client-in-the-aws-sdk-for-java-2-x/
Ответ №3:
в качестве дополнения к другим ответам, для меня работал только вариант 4 из ссылки.
Вариант 4. Измените HTTP-клиент по умолчанию, используя системное свойство в коде Java.
Я определил его по setUp()
методу моего интеграционного теста с использованием JUnit 5.
@BeforeAll
public static void setUp() {
System.setProperty(
SdkSystemSetting.SYNC_HTTP_SERVICE_IMPL.property(),
"software.amazon.awssdk.http.apache.ApacheSdkHttpService");
}
и потому, что я использую gradle:
implementation ("software.amazon.awssdk:s3:${awssdk2Version}") {
exclude group: 'software.amazon.awssdk', module: 'netty-nio-client'
exclude group: 'software.amazon.awssdk', module: 'apache-client'
}
implementation "software.amazon.awssdk:aws-crt-client:2.17.71-PREVIEW"