0

I am trying to follow the hexagonal design of ports and adapters and more specifically following this approach: https://docs.microsoft.com/en-us/archive/blogs/ericgu/unit-test-success-using-ports-adapters-simulatorskata-walkthrough and https://docs.microsoft.com/en-us/archive/blogs/ericgu/unit-test-success-using-ports-adapters-and-simulators.

The main idea is I didn't want to mock out my usage of dynamodb, but create an adapter for it.

Given the interface:

public interface Metadata {
    JsonNode getMetadata(String metadataName, String metadataVersion);
}

And created two implementations. This one actually uses the database:

public enum Dynamodbv2Metadata implements Metadata {

  INSTANCE;
    private AmazonDynamoDB ddb;
    private Dynamodbv2Metadata() {
        ddb = AmazonDynamoDBClientBuilder.defaultClient();
    }

    @Override
    public JsonNode getMetadata(String metadataName, String metadataVersion) {
    //business logic
}

}

While this one uses an in-memory solution known as DynamodbLocal:

public class DynamodbLocalMetadata implements Metadata {
    static ObjectMapper mapper = new ObjectMapper();
    AmazonDynamoDB dynamodb;
    String tableName;
    String partitionKey;

    DynamodbLocalMetadata(String tableName, String hashKeyName, JsonNode dynamodbItem) {
        this.tableName = tableName;
        this.partitionKey = hashKeyName;
        dynamodb = DynamoDBEmbedded.create().amazonDynamoDB();
        // This is here to populate the in-memory database with the records to be tested.
        CreateTableResult res = createTable(dynamodb, tableName, hashKeyName);
        createItem(tableName, dynamodbItem);
    }

    @Override
    public JsonNode getMetadata(String metadataName, String metadataVersion) {
}
}

But my confusion lies on the usage of a simulator. The idea seems to be that I can create a test that would work on both interfaces, and in theory I can, but the initialization would be Metadata metadata = new Dynamodbv2Metadata(); vs Metadata metadata = new DynamodbLocalMetadata();

So is there a way to clean that up so the tests can be the same? At the moment I am not sure what the DynamodbLocalMetadata is giving me since the code uses the Dynamodbv2Metadata implementation when running in local or on a server, but it would call DynamodbLocalMetadata while the unit tests execute.

Any help is appreciated!

user2820906
  • 127
  • 9

1 Answers1

1

The point is to have just a class implementing your interface "MetaData". That class would contain the business logic, and it would depend on a database interface (it would take the db interface as a constructor parameter).

You should create 2 implementations of the db interface: one for the real db, and another for the in-memory db.

Then when running the app you inject either one or the other in the business logic class.

choquero70
  • 3,332
  • 2
  • 24
  • 40