Reputation: 217
I am trying to follow the hexagonal design of ports and adapters and more specifically following this approach: https://learn.microsoft.com/en-us/archive/blogs/ericgu/unit-test-success-using-ports-adapters-simulatorskata-walkthrough and https://learn.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!
Upvotes: 0
Views: 61
Reputation: 4754
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.
Upvotes: 1