2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.awattar.internal.handler;
15 import static org.hamcrest.MatcherAssert.assertThat;
16 import static org.hamcrest.Matchers.is;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.when;
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Method;
22 import java.time.ZoneId;
23 import java.util.List;
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jetty.client.HttpClient;
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29 import org.junit.jupiter.api.extension.ExtendWith;
30 import org.junit.platform.commons.support.HierarchyTraversalMode;
31 import org.junit.platform.commons.support.ReflectionSupport;
32 import org.mockito.Mock;
33 import org.mockito.junit.jupiter.MockitoExtension;
34 import org.mockito.junit.jupiter.MockitoSettings;
35 import org.mockito.quality.Strictness;
36 import org.openhab.binding.awattar.internal.AwattarBindingConstants;
37 import org.openhab.binding.awattar.internal.api.AwattarApi;
38 import org.openhab.binding.awattar.internal.api.AwattarApi.AwattarApiException;
39 import org.openhab.core.i18n.TimeZoneProvider;
40 import org.openhab.core.test.java.JavaTest;
41 import org.openhab.core.thing.Bridge;
42 import org.openhab.core.thing.Thing;
43 import org.openhab.core.thing.ThingStatus;
44 import org.openhab.core.thing.ThingStatusDetail;
45 import org.openhab.core.thing.ThingStatusInfo;
46 import org.openhab.core.thing.ThingUID;
47 import org.openhab.core.thing.binding.ThingHandlerCallback;
50 * The {@link AwattarBridgeHandlerRefreshTest} contains tests for the
51 * {@link AwattarBridgeHandler} refresh logic.
53 * @author Thomas Leber - Initial contribution
55 @ExtendWith(MockitoExtension.class)
56 @MockitoSettings(strictness = Strictness.LENIENT)
58 class AwattarBridgeHandlerRefreshTest extends JavaTest {
59 public static final ThingUID BRIDGE_UID = new ThingUID(AwattarBindingConstants.THING_TYPE_BRIDGE, "testBridge");
62 private @Mock @NonNullByDefault({}) Bridge bridgeMock;
63 private @Mock @NonNullByDefault({}) ThingHandlerCallback bridgeCallbackMock;
64 private @Mock @NonNullByDefault({}) HttpClient httpClientMock;
65 private @Mock @NonNullByDefault({}) TimeZoneProvider timeZoneProviderMock;
66 private @Mock @NonNullByDefault({}) AwattarApi awattarApiMock;
68 // best price handler mocks
69 private @Mock @NonNullByDefault({}) Thing bestpriceMock;
70 private @Mock @NonNullByDefault({}) ThingHandlerCallback bestPriceCallbackMock;
72 private @NonNullByDefault({}) AwattarBridgeHandler bridgeHandler;
75 public void setUp() throws IllegalArgumentException, IllegalAccessException {
77 when(timeZoneProviderMock.getTimeZone()).thenReturn(ZoneId.of("GMT+2"));
79 when(bridgeMock.getUID()).thenReturn(BRIDGE_UID);
80 bridgeHandler = new AwattarBridgeHandler(bridgeMock, httpClientMock, timeZoneProviderMock);
81 bridgeHandler.setCallback(bridgeCallbackMock);
83 List<Field> fields = ReflectionSupport.findFields(AwattarBridgeHandler.class,
84 field -> field.getName().equals("awattarApi"), HierarchyTraversalMode.BOTTOM_UP);
86 for (Field field : fields) {
87 field.setAccessible(true);
88 field.set(bridgeHandler, awattarApiMock);
93 * Test the refreshIfNeeded method with a bridge that is offline.
95 * @throws SecurityException
96 * @throws AwattarApiException
99 void testRefreshIfNeeded_ThingOffline() throws SecurityException, AwattarApiException {
100 when(bridgeMock.getStatus()).thenReturn(ThingStatus.OFFLINE);
102 bridgeHandler.refreshIfNeeded();
104 verify(bridgeCallbackMock).statusUpdated(bridgeMock,
105 new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null));
106 verify(awattarApiMock).getData();
110 * Test the refreshIfNeeded method with a bridge that is online and the data is
113 * @throws SecurityException
114 * @throws AwattarApiException
117 void testRefreshIfNeeded_DataEmpty() throws SecurityException, AwattarApiException {
118 when(bridgeMock.getStatus()).thenReturn(ThingStatus.ONLINE);
120 bridgeHandler.refreshIfNeeded();
122 verify(bridgeCallbackMock).statusUpdated(bridgeMock,
123 new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null));
124 verify(awattarApiMock).getData();
128 void testNeedRefresh_ThingOffline() throws SecurityException {
129 when(bridgeMock.getStatus()).thenReturn(ThingStatus.OFFLINE);
131 // get private method via reflection
132 Method method = ReflectionSupport.findMethod(AwattarBridgeHandler.class, "needRefresh", "").get();
134 boolean result = (boolean) ReflectionSupport.invokeMethod(method, bridgeHandler);
136 assertThat(result, is(true));
140 void testNeedRefresh_DataEmpty() throws SecurityException, IllegalArgumentException, IllegalAccessException {
141 when(bridgeMock.getStatus()).thenReturn(ThingStatus.ONLINE);
143 List<Field> fields = ReflectionSupport.findFields(AwattarBridgeHandler.class,
144 field -> field.getName().equals("prices"), HierarchyTraversalMode.BOTTOM_UP);
146 for (Field field : fields) {
147 field.setAccessible(true);
148 field.set(bridgeHandler, null);
151 // get private method via reflection
152 Method method = ReflectionSupport.findMethod(AwattarBridgeHandler.class, "needRefresh", "").get();
154 boolean result = (boolean) ReflectionSupport.invokeMethod(method, bridgeHandler);
156 assertThat(result, is(true));