From 0cd1bf4dec8f33359aa6a5295063775e48623cca Mon Sep 17 00:00:00 2001 From: "Lerch, Kay" Date: Sun, 11 Sep 2016 20:40:06 +0200 Subject: [PATCH] Sonar test coverage and bug fixing --- pom.xml | 50 ++++++++++++++++++- .../state/handler/AWSDynamoStateHandler.java | 10 ++-- .../state/handler/AWSIotStateHandler.java | 6 +-- .../state/handler/AWSS3StateHandler.java | 4 +- .../handler/AlexaSessionStateHandler.java | 1 - .../alexa/state/utils/ConversionUtils.java | 13 +++-- .../handler/AWSDynamoStateHandlerTest.java | 26 ++++++++-- .../state/handler/AWSIotStateHandlerTest.java | 1 - .../state/handler/AWSS3StateHandlerTest.java | 5 +- .../state/handler/AlexaStateHandlerTest.java | 7 +++ 10 files changed, 102 insertions(+), 21 deletions(-) diff --git a/pom.xml b/pom.xml index 30b5ad5..b0090ef 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,10 @@ 4.12 1.10.19 1.1.3 + ${project.basedir}/target/surefire-reports + ${project.basedir}/target/jacoco-it.exec + java + target/jacoco.exec @@ -69,6 +73,19 @@ maven-surefire-plugin ${maven.surefire.failsafe.version} + + + + listener + org.sonar.java.jacoco.JUnitListener + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 @@ -113,9 +130,34 @@ org.sonarsource.scanner.maven sonar-maven-plugin 3.1.1 + + + org.jacoco + jacoco-maven-plugin - verify + true + + + agent-for-ut + + prepare-agent + + + + agent-for-it + + prepare-agent-integration + + + + jacoco-site + verify + + report + + + org.apache.maven.plugins @@ -204,6 +246,12 @@ test true + + org.sonarsource.java + sonar-jacoco-listeners + 3.8 + test + \ No newline at end of file diff --git a/src/main/java/io/klerch/alexa/state/handler/AWSDynamoStateHandler.java b/src/main/java/io/klerch/alexa/state/handler/AWSDynamoStateHandler.java index 0fb3485..a258005 100644 --- a/src/main/java/io/klerch/alexa/state/handler/AWSDynamoStateHandler.java +++ b/src/main/java/io/klerch/alexa/state/handler/AWSDynamoStateHandler.java @@ -31,11 +31,11 @@ public class AWSDynamoStateHandler extends AlexaSessionStateHandler { private final String tableName; private final long readCapacityUnits; private final long writeCapacityUnits; - private final String tablePrefix = "alexa-"; - private final String attributeValueApp = "__application"; - private final String pkModel = "model-class"; - private final String pkUser = "amzn-user-id"; - private final String attributeKeyState = "state"; + private static final String tablePrefix = "alexa-"; + private static final String attributeValueApp = "__application"; + private static final String pkModel = "model-class"; + private static final String pkUser = "amzn-user-id"; + private static final String attributeKeyState = "state"; private Boolean tableExistenceApproved = false; /** diff --git a/src/main/java/io/klerch/alexa/state/handler/AWSIotStateHandler.java b/src/main/java/io/klerch/alexa/state/handler/AWSIotStateHandler.java index 11d582e..7fdcf7b 100644 --- a/src/main/java/io/klerch/alexa/state/handler/AWSIotStateHandler.java +++ b/src/main/java/io/klerch/alexa/state/handler/AWSIotStateHandler.java @@ -47,9 +47,9 @@ public class AWSIotStateHandler extends AlexaSessionStateHandler { private final AWSIot awsClient; private final AWSIotData awsDataClient; - private final String thingAttributeName = "name"; - private final String thingAttributeUser = "amzn-user-id"; - private final String thingAttributeApp = "amzn-app-id"; + private static final String thingAttributeName = "name"; + private static final String thingAttributeUser = "amzn-user-id"; + private static final String thingAttributeApp = "amzn-app-id"; private List thingsExisting = new ArrayList<>(); public AWSIotStateHandler(final Session session) { diff --git a/src/main/java/io/klerch/alexa/state/handler/AWSS3StateHandler.java b/src/main/java/io/klerch/alexa/state/handler/AWSS3StateHandler.java index 6e9e6ed..6367bee 100644 --- a/src/main/java/io/klerch/alexa/state/handler/AWSS3StateHandler.java +++ b/src/main/java/io/klerch/alexa/state/handler/AWSS3StateHandler.java @@ -32,8 +32,8 @@ public class AWSS3StateHandler extends AlexaSessionStateHandler { private final AmazonS3 awsClient; private final String bucketName; - private final String folderNameApp = "__application"; - private final String fileExtension = "json"; + private static final String folderNameApp = "__application"; + private static final String fileExtension = "json"; /** * Takes the Alexa session. An AWS client for accessing the S3 bucket will make use diff --git a/src/main/java/io/klerch/alexa/state/handler/AlexaSessionStateHandler.java b/src/main/java/io/klerch/alexa/state/handler/AlexaSessionStateHandler.java index 1b87175..ea4cd68 100644 --- a/src/main/java/io/klerch/alexa/state/handler/AlexaSessionStateHandler.java +++ b/src/main/java/io/klerch/alexa/state/handler/AlexaSessionStateHandler.java @@ -13,7 +13,6 @@ import io.klerch.alexa.state.utils.AlexaStateException; import org.apache.log4j.Logger; -import java.lang.reflect.Field; import java.util.Map; import java.util.Optional; diff --git a/src/main/java/io/klerch/alexa/state/utils/ConversionUtils.java b/src/main/java/io/klerch/alexa/state/utils/ConversionUtils.java index 27db027..3469fbc 100644 --- a/src/main/java/io/klerch/alexa/state/utils/ConversionUtils.java +++ b/src/main/java/io/klerch/alexa/state/utils/ConversionUtils.java @@ -8,13 +8,18 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.lang3.Validate; +import org.apache.log4j.Logger; import java.io.IOException; import java.util.HashMap; import java.util.Map; +/** + * Some utils to convert data structures + */ public class ConversionUtils { + private static final Logger log = Logger.getLogger(ConversionUtils.class); + /** * A json-string of key-value pairs is read out as a map * @param json json-string of key-value pairs @@ -22,13 +27,15 @@ public class ConversionUtils { */ public static Map mapJson(final String json) { final ObjectMapper mapper = new ObjectMapper(); - if (json == null || json.isEmpty()) new HashMap<>(); + if (json == null || json.isEmpty()) { + return new HashMap<>(); + } final TypeReference> typeRef = new TypeReference>() {}; try { // read jsonString into map return mapper.readValue(json, typeRef); } catch (IOException e) { - e.printStackTrace(); + log.error(e); return new HashMap<>(); } } diff --git a/src/test/java/io/klerch/alexa/state/handler/AWSDynamoStateHandlerTest.java b/src/test/java/io/klerch/alexa/state/handler/AWSDynamoStateHandlerTest.java index 24f754e..11c4c5a 100644 --- a/src/test/java/io/klerch/alexa/state/handler/AWSDynamoStateHandlerTest.java +++ b/src/test/java/io/klerch/alexa/state/handler/AWSDynamoStateHandlerTest.java @@ -7,8 +7,7 @@ package io.klerch.alexa.state.handler; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; +import com.amazonaws.services.dynamodbv2.model.*; import io.klerch.alexa.state.model.dummies.Model; import org.junit.Test; import org.mockito.Mockito; @@ -17,15 +16,17 @@ import java.util.Map; import static org.junit.Assert.*; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; public class AWSDynamoStateHandlerTest extends AlexaStateHandlerTest { - private final String tableName = "tableName"; @Override public AWSDynamoStateHandler getHandler() { final AmazonDynamoDBClient awsClient = mock(AmazonDynamoDBClient.class); - handler = new AWSDynamoStateHandler(session, awsClient, tableName); + handler = new AWSDynamoStateHandler(session, awsClient); + + final String tableName = handler.getTableName(); // prepare static read return from DynamoDB without given model-Id final String jsonApp = "{\"id\":null,\"sampleApplication\":true}"; @@ -59,10 +60,27 @@ public AWSDynamoStateHandler getHandler() { final GetItemResult resultUserId = new GetItemResult().withItem(mapUserId); final GetItemResult resultAppId = new GetItemResult().withItem(mapAppId); + // mock get items for model with id Mockito.when(awsClient.getItem(tableName, handler.getUserScopedKeyAttributes(Model.class, modelId))) .thenReturn(resultUserId); Mockito.when(awsClient.getItem(tableName, handler.getAppScopedKeyAttributes(Model.class, modelId))) .thenReturn(resultAppId); + + // mock get items for absent model (with empty response) + Mockito.when(awsClient.getItem(tableName, handler.getUserScopedKeyAttributes(Model.class, absentModelId))) + .thenReturn(new GetItemResult()); + Mockito.when(awsClient.getItem(tableName, handler.getAppScopedKeyAttributes(Model.class, absentModelId))) + .thenReturn(new GetItemResult()); + + // on create table call always return table in ACTIVE state + final TableDescription tableDescription = new TableDescription().withTableName(tableName).withTableStatus(TableStatus.ACTIVE); + final CreateTableResult createResult = new CreateTableResult().withTableDescription(tableDescription); + Mockito.when(awsClient.createTable(any(CreateTableRequest.class))).thenReturn(createResult); + + // mock describe table request to always return a table whose name is + final DescribeTableResult describeResult = new DescribeTableResult().withTable(tableDescription); + Mockito.when(awsClient.describeTable(any(DescribeTableRequest.class))).thenReturn(describeResult); + return handler; } diff --git a/src/test/java/io/klerch/alexa/state/handler/AWSIotStateHandlerTest.java b/src/test/java/io/klerch/alexa/state/handler/AWSIotStateHandlerTest.java index 3f36d85..1eaca26 100644 --- a/src/test/java/io/klerch/alexa/state/handler/AWSIotStateHandlerTest.java +++ b/src/test/java/io/klerch/alexa/state/handler/AWSIotStateHandlerTest.java @@ -49,7 +49,6 @@ public Object answer(InvocationOnMock invocationOnMock) throws Throwable { if (invocationOnMock.getMethod().getName().equals("getThingShadow")) { // build shadow JSON with reported state for Model with one // instance having an id and another having no id - final AWSIotStateHandler handler = new AWSIotStateHandler(session); final String keyWithId = AlexaStateModel.getAttributeKey(Model.class, modelId); final String keyWithoutId = AlexaStateModel.getAttributeKey(Model.class, null); final String jsonWithId = "\"" + keyWithId + "\":{\"id\":\"" + modelId + "\",\"sampleApplication\":true,\"sampleUser\":\"sampleUser\"}"; diff --git a/src/test/java/io/klerch/alexa/state/handler/AWSS3StateHandlerTest.java b/src/test/java/io/klerch/alexa/state/handler/AWSS3StateHandlerTest.java index a794b50..dbff6f8 100644 --- a/src/test/java/io/klerch/alexa/state/handler/AWSS3StateHandlerTest.java +++ b/src/test/java/io/klerch/alexa/state/handler/AWSS3StateHandlerTest.java @@ -29,7 +29,10 @@ public AWSS3StateHandler getHandler() { final AmazonS3Client s3Client = Mockito.mock(AmazonS3Client.class, new Answer() { @Override public Object answer(InvocationOnMock invocationOnMock) throws Throwable { - if (invocationOnMock.getMethod().getName().equals("doesObjectExist")) return true; + if (invocationOnMock.getMethod().getName().equals("doesObjectExist")) { + // true in case of any model requested beside the one assumed as absent + return !(Arrays.stream(invocationOnMock.getArguments()).filter(p -> p.toString().contains(absentModelId)).findAny().isPresent()); + } if (invocationOnMock.getMethod().getName().equals("putObject")) return new PutObjectResult(); if (invocationOnMock.getMethod().getName().equals("deleteObject")) return null; if (invocationOnMock.getMethod().getName().equals("getObject")) { diff --git a/src/test/java/io/klerch/alexa/state/handler/AlexaStateHandlerTest.java b/src/test/java/io/klerch/alexa/state/handler/AlexaStateHandlerTest.java index 9806d1f..94d1f2b 100644 --- a/src/test/java/io/klerch/alexa/state/handler/AlexaStateHandlerTest.java +++ b/src/test/java/io/klerch/alexa/state/handler/AlexaStateHandlerTest.java @@ -10,6 +10,7 @@ import com.amazon.speech.speechlet.Session; import com.amazon.speech.speechlet.User; import io.klerch.alexa.state.model.dummies.Model; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -23,6 +24,7 @@ public abstract class AlexaStateHandlerTest THandler handler; Session session; final String modelId = "modelId"; + final String absentModelId = "nonexisting"; public abstract THandler getHandler(); @@ -95,6 +97,11 @@ public void crudModel() throws Exception { assertFalse(session.getAttributes().containsKey(key)); } + @Test + public void readAbsentModel() throws Exception { + Assert.assertFalse(handler.readModel(Model.class, absentModelId).isPresent()); + } + @Test public void crudModelWithId() throws Exception { session.getAttributes().clear();