I test for update properties action (#257)

* UNOMI-418: provide Integration test for recent fix on UpdatePropertiesAction

* UNOMI-418: make all test waiting for unomi full startup for more stability
diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
index ffa9be9..6d70345 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -22,18 +22,26 @@
 import org.apache.unomi.api.Item;
 import org.apache.unomi.api.conditions.Condition;
 import org.apache.unomi.api.services.DefinitionsService;
+import org.apache.unomi.lifecycle.BundleWatcher;
 import org.apache.unomi.persistence.spi.CustomObjectMapper;
 import org.apache.unomi.persistence.spi.PersistenceService;
 import org.junit.Assert;
+import org.junit.Before;
+import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.CoreOptions;
 import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.karaf.container.internal.JavaVersionUtil;
 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
 import org.ops4j.pax.exam.options.MavenArtifactUrlReference;
 import org.ops4j.pax.exam.options.extra.VMOption;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerSuite;
 import org.ops4j.pax.exam.util.Filter;
 import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.inject.Inject;
 import java.io.File;
@@ -54,7 +62,11 @@
  * 
  * @author kevan
  */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerSuite.class)
 public abstract class BaseIT {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(BaseIT.class);
     
     protected static final String HTTP_PORT = "8181";
     protected static final String URL = "http://localhost:" + HTTP_PORT;
@@ -72,6 +84,17 @@
     @Inject
     protected BundleContext bundleContext;
 
+    @Inject @Filter(timeout = 600000)
+    protected BundleWatcher bundleWatcher;
+
+    @Before
+    public void waitForStartup() throws InterruptedException {
+        while (!bundleWatcher.isStartupComplete()) {
+            LOGGER.info("Waiting for startup to complete...");
+            Thread.sleep(1000);
+        }
+    }
+
     protected void removeItems(final Class<? extends Item> ...classes) throws InterruptedException {
         Condition condition = new Condition(definitionsService.getConditionType("matchAllCondition"));
         for (Class<? extends Item> aClass : classes) {
diff --git a/itests/src/test/java/org/apache/unomi/itests/BasicIT.java b/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
index 232ced3..1f7299e 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
@@ -92,16 +92,6 @@
     protected ProfileService profileService;
     @Inject @Filter(timeout = 600000)
     protected DefinitionsService definitionsService;
-    @Inject @Filter(timeout = 600000)
-    protected BundleWatcher bundleWatcher;
-
-    @Before
-    public void setUp() throws InterruptedException {
-        while (!bundleWatcher.isStartupComplete()) {
-            LOGGER.info("Waiting for startup to complete...");
-            Thread.sleep(1000);
-        }
-    }
 
     @Test
     public void testContextJS() throws IOException {
diff --git a/itests/src/test/java/org/apache/unomi/itests/PropertiesUpdateActionIT.java b/itests/src/test/java/org/apache/unomi/itests/PropertiesUpdateActionIT.java
index f1b6304..f161632 100644
--- a/itests/src/test/java/org/apache/unomi/itests/PropertiesUpdateActionIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/PropertiesUpdateActionIT.java
@@ -58,6 +58,9 @@
     public void setUp() throws IOException, InterruptedException {
         Profile profile = new Profile();
         profile.setItemId(PROFILE_TEST_ID);
+        profile.setProperties(new HashMap<>());
+        profile.setProperty("lastName", "Jose"); // property that have a propertyType registered in the system
+        profile.setProperty("prop4", "New property 4"); // property that do not have a propertyType registered in the system
         profileService.save(profile);
         LOGGER.info("Profile saved with ID [{}].", profile.getItemId());
 
@@ -124,6 +127,8 @@
         propertyToAdd.put("properties.prop1", "New property 1");
         propertyToAdd.put("properties.prop2", "New property 2");
         propertyToAdd.put("properties.prop3", "New property 3");
+        propertyToAdd.put("properties.prop4", "Updated property 4");
+        propertyToAdd.put("properties.lastName", "Michel");
 
         updateProperties.setProperty(UpdatePropertiesAction.PROPS_TO_ADD, propertyToAdd);
         updateProperties.setProperty(UpdatePropertiesAction.TARGET_ID_KEY, PROFILE_TEST_ID);
@@ -133,9 +138,11 @@
         refreshPersistence();
 
         profile = profileService.load(PROFILE_TEST_ID);
-        Assert.assertEquals("New property 1", profile.getProperty("prop1"));
-        Assert.assertEquals("New property 2", profile.getProperty("prop2"));
-        Assert.assertEquals("New property 3", profile.getProperty("prop3"));
+        Assert.assertEquals("Props_to_add should set the prop if it's missing", "New property 1", profile.getProperty("prop1"));
+        Assert.assertEquals("Props_to_add should set the prop if it's missing", "New property 2", profile.getProperty("prop2"));
+        Assert.assertEquals("Props_to_add should set the prop if it's missing", "New property 3", profile.getProperty("prop3"));
+        Assert.assertEquals("Props_to_add should not override existing prop", "New property 4", profile.getProperty("prop4"));
+        Assert.assertEquals("Props_to_add should not override existing prop", "Jose", profile.getProperty("lastName"));
     }
 
     @Test
diff --git a/itests/src/test/java/org/apache/unomi/itests/SecurityIT.java b/itests/src/test/java/org/apache/unomi/itests/SecurityIT.java
index b90e953..f423622 100644
--- a/itests/src/test/java/org/apache/unomi/itests/SecurityIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/SecurityIT.java
@@ -49,22 +49,12 @@
 @ExamReactorStrategy(PerSuite.class)
 public class SecurityIT extends BaseIT {
 
-    private final static Logger LOGGER = LoggerFactory.getLogger(SecurityIT.class);
-
     private static final String SESSION_ID = "vuln-session-id";
 
     private ObjectMapper objectMapper;
 
-    @Inject
-    @Filter(timeout = 600000)
-    protected BundleWatcher bundleWatcher;
-
     @Before
     public void setUp() throws InterruptedException {
-        while (!bundleWatcher.isStartupComplete()) {
-            LOGGER.info("Waiting for startup to complete...");
-            Thread.sleep(1000);
-        }
         objectMapper = CustomObjectMapper.getObjectMapper();
     }
 
diff --git a/itests/src/test/java/org/apache/unomi/itests/SegmentIT.java b/itests/src/test/java/org/apache/unomi/itests/SegmentIT.java
index 1ca2e8b..fceb70c 100644
--- a/itests/src/test/java/org/apache/unomi/itests/SegmentIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/SegmentIT.java
@@ -22,7 +22,6 @@
 import org.apache.unomi.api.segments.Segment;
 import org.apache.unomi.api.services.SegmentService;
 import org.apache.unomi.api.exceptions.BadSegmentConditionException;
-import org.apache.unomi.lifecycle.BundleWatcher;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -47,15 +46,8 @@
     @Filter(timeout = 600000)
     protected SegmentService segmentService;
 
-    @Inject @Filter(timeout = 600000)
-    protected BundleWatcher bundleWatcher;
-
     @Before
     public void setUp() throws InterruptedException {
-        while (!bundleWatcher.isStartupComplete()) {
-            LOGGER.info("Waiting for startup to complete...");
-            Thread.sleep(1000);
-        }
         removeItems(Segment.class);
     }
 
diff --git a/itests/src/test/java/org/apache/unomi/itests/graphql/BaseGraphQLIT.java b/itests/src/test/java/org/apache/unomi/itests/graphql/BaseGraphQLIT.java
index df3e8b0..d2d76c3 100644
--- a/itests/src/test/java/org/apache/unomi/itests/graphql/BaseGraphQLIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/graphql/BaseGraphQLIT.java
@@ -53,17 +53,6 @@
     @Inject
     protected BundleContext bundleContext;
 
-    @Inject
-    @Filter(timeout = 600000)
-    protected BundleWatcher bundleWatcher;
-
-    @Before
-    public void setUp() throws InterruptedException {
-        while (!bundleWatcher.isStartupComplete()) {
-            Thread.sleep(1000);
-        }
-    }
-
     protected CloseableHttpResponse post(final String resource) throws IOException {
         final String resourceAsString = resourceAsString(resource);
 
diff --git a/itests/src/test/java/org/apache/unomi/itests/graphql/GraphQLEventIT.java b/itests/src/test/java/org/apache/unomi/itests/graphql/GraphQLEventIT.java
index ad514e2..5c9e02d 100644
--- a/itests/src/test/java/org/apache/unomi/itests/graphql/GraphQLEventIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/graphql/GraphQLEventIT.java
@@ -53,7 +53,6 @@
 
     @Before
     public void setUp() throws InterruptedException {
-        super.setUp();
         profile = new Profile(profileID);
         persistenceService.save(profile);