0

I can't figure out how to use Testcontainers' Dynalite module in a JUnit 5 test to be able to test Amazon DynamoDB, - documentation is really too succinct and minimalist.

So I added the following dependencies in pom.xml:

<dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>${junit.jupiter.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-dynamodb</artifactId>
            <version>1.11.842</version>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>testcontainers</artifactId>
            <version>${testcontainers.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>dynalite</artifactId>
            <version>${testcontainers.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>${testcontainers.version}</version>
            <scope>test</scope>
        </dependency>

where testcontainers.version is 1.14.3 and junit.jupiter.version is 5.6.2. Then I created a service test class as follows:

@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DailyPowerConsumptionServiceTest {

    @Container
    public static DynaliteContainer dynaliteContainer = new DynaliteContainer();

@TestConfiguration
    static class UserServiceImplTestContextConfiguration {

        @Bean
        DailyPowerConsumptionService dailyPowerConsumptionService() {
            return new DailyPowerConsumptionServiceImpl();
        }
    }

    @Autowired
    private DailyPowerConsumptionRepository repository;

    @Autowired
    private DailyPowerConsumptionService dailyPowerConsumptionService;

    @BeforeClass
    public void setUp() {
        AmazonDynamoDB amazonDynamoDB = dynaliteContainer.getClient();
        DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
        CreateTableRequest tableRequest = dynamoDBMapper
                .generateCreateTableRequest(DailyPowerConsumption.class);
        tableRequest.setProvisionedThroughput(
                new ProvisionedThroughput(1L, 1L));
        amazonDynamoDB.createTable(tableRequest);

        dynamoDBMapper.batchDelete(repository.findAll());
    }

    @Test
    void findDailyPowerConsumptions() {
        assertTrue(dynaliteContainer.isRunning());
    }
}

When running the tests, it works, yay!

But when I try to create an entry and test the service as follows:

    @Test
    void findDailyPowerConsumptions() throws SQLException {
        //assertTrue(dynaliteContainer.isRunning());
        DailyPowerConsumption dailyPowerConsumption = new DailyPowerConsumption(1, 10, "2020-08-10.000", "DEV1", 10.0,
        10.0, 220.0, 10.0, 1.0,1.0, 1.0);

        repository.save(dailyPowerConsumption);

        List<DailyPowerConsumption> dailyPowerConsumptionsList = dailyPowerConsumptionService.findDailyPowerConsumptions("EX1", "1", "10");
        assertThat(dailyPowerConsumptionsList).isNotEmpty();
    }

it fails with:

com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: The provided key element does not match the schema (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 71B6U0QKNDARKLUEBQQ99B6DD7VV4KQNSO5AEMVJF66Q9ASUAAJG; Proxy: null)

What am I missing here? I checked the mapped values, they seem to be OK.

belgoros
  • 3,590
  • 7
  • 38
  • 76
  • Which AWS Dynamo Client is your `repository` using? If this is using a client _connecting_ to the real AWS, then I guess you also have to override this bean and point the AWS SDK to connect for the Dynamo Client to your local db – rieckpil Aug 18 '20 at 12:49
  • The purpose of using Dynalite is to avoid any local DynamoDB setup. In this case, everything is run in a Docker container. The error message is really weird and has nothing related to that. – belgoros Aug 18 '20 at 12:52
  • I'm aware of this, but any production code of you pointing to the _real_ AWS DB needs to be overridden to connect to localhost. You might want to check the following example: https://rieckpil.de/test-spring-applications-using-aws-with-testcontainers-and-localstack/. Even though I'm aware that this is *not* Dynalite, it explains what you need to override – rieckpil Aug 18 '20 at 12:54
  • I do have real AWS credentials defined in `src/main/resources/application.properties`(endpoint, accesskey, secretkey) but have no idea what values to put in `test/resources/application.properties` and how to set them in tests. – belgoros Aug 18 '20 at 12:59
  • That's why, when mocking the repository calls, it works :) – belgoros Aug 18 '20 at 12:59
  • @belgoros try putting a pause [Thread.sleep(1000) ] in your setup() method ,once you create the table (after amazonDynamoDB.createTable(tableRequest);). I've observed that the table creation takes some time. – Sandeep Lakdawala Aug 18 '20 at 17:27

0 Answers0