diff --git a/extensions/binding/org.eclipse.smarthome.binding.onewire.test/src/test/java/org/eclipse/smarthome/binding/onewire/internal/OwserverBridgeHandlerTest.java b/extensions/binding/org.eclipse.smarthome.binding.onewire.test/src/test/java/org/eclipse/smarthome/binding/onewire/internal/OwserverBridgeHandlerTest.java index 5d7c6b037db..4fb92263c83 100644 --- a/extensions/binding/org.eclipse.smarthome.binding.onewire.test/src/test/java/org/eclipse/smarthome/binding/onewire/internal/OwserverBridgeHandlerTest.java +++ b/extensions/binding/org.eclipse.smarthome.binding.onewire.test/src/test/java/org/eclipse/smarthome/binding/onewire/internal/OwserverBridgeHandlerTest.java @@ -13,9 +13,11 @@ package org.eclipse.smarthome.binding.onewire.internal; import static org.eclipse.smarthome.binding.onewire.internal.OwBindingConstants.*; +import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.timeout; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; +import static org.mockito.MockitoAnnotations.initMocks; import java.util.HashMap; import java.util.Map; @@ -27,15 +29,16 @@ import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusInfo; import org.eclipse.smarthome.core.thing.binding.ThingHandlerCallback; import org.eclipse.smarthome.core.thing.binding.builder.BridgeBuilder; import org.eclipse.smarthome.test.java.JavaTest; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; /** * Tests cases for {@link OwserverBridgeHandler}. @@ -63,12 +66,12 @@ public void setup() { bridgeProperties.put(CONFIG_ADDRESS, TEST_HOST); bridgeProperties.put(CONFIG_PORT, TEST_PORT); - MockitoAnnotations.initMocks(this); + initMocks(this); bridge = BridgeBuilder.create(THING_TYPE_OWSERVER, "owserver").withLabel("owserver") .withConfiguration(new Configuration(bridgeProperties)).build(); - Mockito.doAnswer(answer -> { + doAnswer(answer -> { ((Thing) answer.getArgument(0)).setStatusInfo(answer.getArgument(1)); return null; }).when(thingHandlerCallback).statusUpdated(any(), any()); @@ -102,8 +105,14 @@ public void testInitializationReportsRefreshableOnSuccessfullConnection() { bridgeHandler.initialize(); + ArgumentCaptor statusCaptor = ArgumentCaptor.forClass(ThingStatusInfo.class); + waitForAssert(() -> { + verify(thingHandlerCallback, times(2)).statusUpdated(eq(bridge), statusCaptor.capture()); + }); + assertThat(statusCaptor.getAllValues().get(0).getStatus(), is(ThingStatus.UNKNOWN)); + assertThat(statusCaptor.getAllValues().get(1).getStatus(), is(ThingStatus.ONLINE)); + waitForAssert(() -> assertTrue(bridgeHandler.isRefreshable())); - waitForAssert(() -> assertEquals(ThingStatus.ONLINE, bridge.getStatusInfo().getStatus())); } @Test @@ -115,8 +124,14 @@ public void testInitializationReportsNotRefreshableOnFailedConnection() { bridgeHandler.initialize(); + ArgumentCaptor statusCaptor = ArgumentCaptor.forClass(ThingStatusInfo.class); + waitForAssert(() -> { + verify(thingHandlerCallback, times(2)).statusUpdated(eq(bridge), statusCaptor.capture()); + }); + assertThat(statusCaptor.getAllValues().get(0).getStatus(), is(ThingStatus.UNKNOWN)); + assertThat(statusCaptor.getAllValues().get(1).getStatus(), is(ThingStatus.OFFLINE)); + waitForAssert(() -> assertFalse(bridgeHandler.isRefreshable())); - waitForAssert(() -> assertEquals(ThingStatus.OFFLINE, bridge.getStatusInfo().getStatus())); } } diff --git a/extensions/binding/org.eclipse.smarthome.binding.onewire/src/main/java/org/eclipse/smarthome/binding/onewire/internal/handler/OwserverBridgeHandler.java b/extensions/binding/org.eclipse.smarthome.binding.onewire/src/main/java/org/eclipse/smarthome/binding/onewire/internal/handler/OwserverBridgeHandler.java index 242c4642282..47f15d3ade4 100644 --- a/extensions/binding/org.eclipse.smarthome.binding.onewire/src/main/java/org/eclipse/smarthome/binding/onewire/internal/handler/OwserverBridgeHandler.java +++ b/extensions/binding/org.eclipse.smarthome.binding.onewire/src/main/java/org/eclipse/smarthome/binding/onewire/internal/handler/OwserverBridgeHandler.java @@ -77,11 +77,13 @@ public void initialize() { owserverConnection.setPort(((BigDecimal) configuration.get(CONFIG_PORT)).intValue()); } + // makes it possible for unit tests to differentiate direct update and + // postponed update through the owserverConnection: + updateStatus(ThingStatus.UNKNOWN); + scheduler.execute(() -> { owserverConnection.start(); }); - - updateStatus(ThingStatus.UNKNOWN); } @Override diff --git a/tools/archetype/binding.test/src/main/resources/archetype-resources/src/test/java/__bindingIdCamelCase__HandlerTest.java b/tools/archetype/binding.test/src/main/resources/archetype-resources/src/test/java/__bindingIdCamelCase__HandlerTest.java index 6f6f0e4e257..712860b9ef1 100644 --- a/tools/archetype/binding.test/src/main/resources/archetype-resources/src/test/java/__bindingIdCamelCase__HandlerTest.java +++ b/tools/archetype/binding.test/src/main/resources/archetype-resources/src/test/java/__bindingIdCamelCase__HandlerTest.java @@ -19,8 +19,8 @@ */ package ${package}; -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; import static org.mockito.MockitoAnnotations.initMocks; @@ -32,6 +32,7 @@ import org.eclipse.smarthome.core.thing.ThingStatusInfo; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerCallback; +import org.eclipse.smarthome.test.java.JavaTest; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -42,7 +43,7 @@ * * @author ${author} - Initial contribution */ -public class ${bindingIdCamelCase}HandlerTest { +public class ${bindingIdCamelCase}HandlerTest extends JavaTest { private ThingHandler handler; @@ -73,11 +74,17 @@ public void initializeShouldCallTheCallback() { ArgumentCaptor statusInfoCaptor = ArgumentCaptor.forClass(ThingStatusInfo.class); // verify the interaction with the callback and capture the ThingStatusInfo argument: - verify(callback).statusUpdated(eq(thing), statusInfoCaptor.capture()); + waitForAssert(() -> { + verify(callback, times(2)).statusUpdated(eq(thing), statusInfoCaptor.capture()); + }); - // assert that the ThingStatusInfo given to the callback was build with the (temporary) UNKNOWN status: - ThingStatusInfo thingStatusInfo = statusInfoCaptor.getValue(); - assertThat(thingStatusInfo.getStatus(), is(equalTo(ThingStatus.UNKNOWN))); + // assert that the (temporary) UNKNOWN status was given first: + assertThat(statusInfoCaptor.getAllValues().get(0).getStatus(), is(ThingStatus.UNKNOWN)); + + + // assert that ONLINE status was given later: + assertThat(statusInfoCaptor.getAllValues().get(1).getStatus(), is(ThingStatus.ONLINE)); + // See the documentation at // https://www.eclipse.org/smarthome/documentation/development/testing.html#assertions diff --git a/tools/archetype/binding/src/main/resources/archetype-resources/src/main/java/internal/__bindingIdCamelCase__Handler.java b/tools/archetype/binding/src/main/resources/archetype-resources/src/main/java/internal/__bindingIdCamelCase__Handler.java index 144c55c5f6d..90bef6b48a9 100644 --- a/tools/archetype/binding/src/main/resources/archetype-resources/src/main/java/internal/__bindingIdCamelCase__Handler.java +++ b/tools/archetype/binding/src/main/resources/archetype-resources/src/main/java/internal/__bindingIdCamelCase__Handler.java @@ -80,20 +80,22 @@ public void initialize() { // access or similar) you should set status UNKNOWN here and then decide the real status asynchronously in the // background. + // set the thing status to UNKNOWN temporarily and let the background task decide for the real status. + // the framework is then able to reuse the resources from the thing handler initialization. + // we set this upfront to reliably check status updates in unit tests. + updateStatus(ThingStatus.UNKNOWN); + // Example for background initialization: scheduler.execute(() -> { boolean thingReachable = true; // // when done do: if (thingReachable) { - // updateStatus(ThingStatus.ONLINE); // commented for stable test execution + updateStatus(ThingStatus.ONLINE); } else { - // updateStatus(ThingStatus.OFFLINE); + updateStatus(ThingStatus.OFFLINE); } }); - // set the thing status to UNKNOWN temporarily and let the background task decide for the real status. - // the framework is then able to reuse the resources from the thing handler initialization. - updateStatus(ThingStatus.UNKNOWN); // logger.debug("Finished initializing!"); // Note: When initialization can NOT be done set the status with more details for further