Skip to content

Commit a0c165c

Browse files
authored
feat: adding model tests (#131)
1 parent 977fb51 commit a0c165c

File tree

5 files changed

+660
-4
lines changed

5 files changed

+660
-4
lines changed

src/main/java/com/bigboxer23/switch_bot/data/Device.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package com.bigboxer23.switch_bot.data;
22

33
import com.squareup.moshi.Json;
4-
import lombok.Data;
5-
64
import java.util.List;
5+
import lombok.Data;
76

87
/** */
98
@Data

src/test/java/com/bigboxer23/switch_bot/SwitchBotApiUnitTest.java

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,96 @@
33
import static org.junit.jupiter.api.Assertions.*;
44
import static org.mockito.Mockito.*;
55

6-
import com.bigboxer23.switch_bot.data.Device;
7-
import com.bigboxer23.switch_bot.data.DeviceCommand;
6+
import com.bigboxer23.switch_bot.data.*;
87
import com.bigboxer23.utils.time.ITimeConstants;
98
import java.io.IOException;
109
import java.util.List;
10+
import java.util.Optional;
11+
import okhttp3.Response;
12+
import org.junit.jupiter.api.BeforeEach;
1113
import org.junit.jupiter.api.Test;
1214

1315
public class SwitchBotApiUnitTest {
16+
17+
@BeforeEach
18+
void resetSingleton() throws Exception {
19+
java.lang.reflect.Field instanceField = SwitchBotApi.class.getDeclaredField("instance");
20+
instanceField.setAccessible(true);
21+
instanceField.set(null, null);
22+
}
23+
1424
@Test
1525
public void testSingletonBehavior() {
1626
SwitchBotApi mockApi1 = SwitchBotApi.getInstance("token", "secret");
1727
SwitchBotApi mockApi2 = SwitchBotApi.getInstance("token", "secret");
1828
assertSame(mockApi1, mockApi2, "Should return the same singleton instance");
1929
}
2030

31+
@Test
32+
public void testGetInstanceWithNullToken() {
33+
RuntimeException exception = assertThrows(RuntimeException.class, () -> {
34+
SwitchBotApi.getInstance(null, "secret");
35+
});
36+
assertEquals("need to define token and secret values.", exception.getMessage());
37+
}
38+
39+
@Test
40+
public void testGetInstanceWithNullSecret() {
41+
RuntimeException exception = assertThrows(RuntimeException.class, () -> {
42+
SwitchBotApi.getInstance("token", null);
43+
});
44+
assertEquals("need to define token and secret values.", exception.getMessage());
45+
}
46+
47+
@Test
48+
public void testAddAuthReturnsCallback() {
49+
assertNotNull(SwitchBotApi.getInstance("testToken", "testSecret"));
50+
}
51+
52+
@Test
53+
public void testCheckForErrorWithSuccessfulResponse() {
54+
SwitchBotApi api = SwitchBotApi.getInstance("token", "secret");
55+
Response mockResponse = mock(Response.class);
56+
ApiResponse successResponse = new ApiResponse();
57+
successResponse.setStatusCode(100);
58+
successResponse.setMessage("success");
59+
60+
IApiResponse result = api.checkForError(mockResponse, Optional.of(successResponse));
61+
62+
assertTrue(result.isSuccess());
63+
assertEquals(100, result.getStatusCode());
64+
}
65+
66+
@Test
67+
public void testCheckForErrorWithFailedResponse() {
68+
SwitchBotApi api = SwitchBotApi.getInstance("token", "secret");
69+
Response mockResponse = mock(Response.class);
70+
ApiResponse failedResponse = new ApiResponse();
71+
failedResponse.setStatusCode(190);
72+
failedResponse.setMessage("Device not found");
73+
74+
IApiResponse result = api.checkForError(mockResponse, Optional.of(failedResponse));
75+
76+
assertFalse(result.isSuccess());
77+
assertEquals(190, result.getStatusCode());
78+
assertEquals("Device not found", result.getMessage());
79+
}
80+
81+
@Test
82+
public void testCheckForErrorWithEmptyResponse() {
83+
SwitchBotApi api = SwitchBotApi.getInstance("token", "secret");
84+
Response mockResponse = mock(Response.class);
85+
when(mockResponse.code()).thenReturn(404);
86+
when(mockResponse.message()).thenReturn("Not Found");
87+
88+
IApiResponse result = api.checkForError(mockResponse, Optional.empty());
89+
90+
assertFalse(result.isSuccess());
91+
assertEquals(404, result.getStatusCode());
92+
assertEquals("Not Found", result.getMessage());
93+
assertInstanceOf(BadApiResponse.class, result);
94+
}
95+
2196
@Test
2297
public void testDeviceCommandSerialization() throws IOException {
2398
SwitchBotApi api = SwitchBotApi.getInstance("token", "secret");
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
package com.bigboxer23.switch_bot;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
import static org.mockito.Mockito.*;
5+
6+
import com.bigboxer23.switch_bot.data.*;
7+
import com.bigboxer23.utils.time.ITimeConstants;
8+
import java.io.IOException;
9+
import java.util.Arrays;
10+
import java.util.Collections;
11+
import org.junit.jupiter.api.BeforeEach;
12+
import org.junit.jupiter.api.Test;
13+
import org.mockito.Mock;
14+
import org.mockito.MockitoAnnotations;
15+
16+
public class SwitchBotDeviceApiTest {
17+
18+
@Mock
19+
private SwitchBotApi mockSwitchBotApi;
20+
21+
private SwitchBotDeviceApi deviceApi;
22+
23+
@BeforeEach
24+
void setUp() {
25+
MockitoAnnotations.openMocks(this);
26+
deviceApi = new SwitchBotDeviceApi(mockSwitchBotApi);
27+
}
28+
29+
@Test
30+
public void testGetDeviceNameFromIdWithFreshCache() throws IOException {
31+
Device device1 = new Device();
32+
device1.setDeviceId("device1");
33+
device1.setDeviceName("Living Room Light");
34+
35+
Device device2 = new Device();
36+
device2.setDeviceId("device2");
37+
device2.setDeviceName("Bedroom Curtain");
38+
39+
SwitchBotDeviceApi spyDeviceApi = spy(deviceApi);
40+
doReturn(Arrays.asList(device1, device2)).when(spyDeviceApi).getDevices();
41+
42+
String result = spyDeviceApi.getDeviceNameFromId("device1");
43+
assertEquals("Living Room Light", result);
44+
45+
String result2 = spyDeviceApi.getDeviceNameFromId("device2");
46+
assertEquals("Bedroom Curtain", result2);
47+
}
48+
49+
@Test
50+
public void testGetDeviceNameFromIdWithUnknownDevice() throws IOException {
51+
Device device = new Device();
52+
device.setDeviceId("known-device");
53+
device.setDeviceName("Known Device");
54+
55+
SwitchBotDeviceApi spyDeviceApi = spy(deviceApi);
56+
doReturn(Arrays.asList(device)).when(spyDeviceApi).getDevices();
57+
58+
String result = spyDeviceApi.getDeviceNameFromId("unknown-device");
59+
assertEquals("unknown-device", result);
60+
}
61+
62+
@Test
63+
public void testGetDeviceNameFromIdCacheExpiry() throws IOException {
64+
Device device = new Device();
65+
device.setDeviceId("device1");
66+
device.setDeviceName("Test Device");
67+
68+
SwitchBotDeviceApi spyDeviceApi = spy(deviceApi);
69+
spyDeviceApi.deviceIdToNamesCacheTime = System.currentTimeMillis() - (ITimeConstants.HOUR * 2);
70+
71+
doReturn(Arrays.asList(device)).when(spyDeviceApi).getDevices();
72+
73+
String result = spyDeviceApi.getDeviceNameFromId("device1");
74+
assertEquals("Test Device", result);
75+
76+
verify(spyDeviceApi, times(1)).getDevices();
77+
}
78+
79+
@Test
80+
public void testGetDeviceNameFromIdWithValidCache() throws IOException {
81+
Device device = new Device();
82+
device.setDeviceId("device1");
83+
device.setDeviceName("Cached Device");
84+
85+
SwitchBotDeviceApi spyDeviceApi = spy(deviceApi);
86+
spyDeviceApi.deviceIdToNamesCacheTime = System.currentTimeMillis();
87+
88+
doReturn(Arrays.asList(device)).when(spyDeviceApi).getDevices();
89+
spyDeviceApi.getDeviceNameFromId("device1");
90+
91+
reset(spyDeviceApi);
92+
spyDeviceApi.deviceIdToNamesCacheTime = System.currentTimeMillis();
93+
spyDeviceApi.getDeviceNameFromId("device1");
94+
95+
verify(spyDeviceApi, never()).getDevices();
96+
}
97+
98+
@Test
99+
public void testGetDeviceNameFromIdWithIOException() throws IOException {
100+
SwitchBotDeviceApi spyDeviceApi = spy(deviceApi);
101+
doThrow(new IOException("Network error")).when(spyDeviceApi).getDevices();
102+
103+
String result = spyDeviceApi.getDeviceNameFromId("device1");
104+
assertEquals("device1", result);
105+
}
106+
107+
@Test
108+
public void testGetDeviceStatusWithNullDeviceId() throws IOException {
109+
Device result = deviceApi.getDeviceStatus(null);
110+
assertNull(result);
111+
}
112+
113+
@Test
114+
public void testGetDeviceStatusInputValidation() {
115+
assertDoesNotThrow(() -> {
116+
assertNotNull(deviceApi);
117+
});
118+
}
119+
120+
@Test
121+
public void testSendDeviceControlCommandsValidation() {
122+
DeviceCommand command = new DeviceCommand("turnOn", "default");
123+
when(mockSwitchBotApi.getMoshi()).thenReturn(new com.squareup.moshi.Moshi.Builder().build());
124+
125+
assertNotNull(command);
126+
assertEquals("turnOn", command.getCommand());
127+
assertEquals("default", command.getParameter());
128+
}
129+
130+
@Test
131+
public void testRefreshDeviceNameMapWithEmptyList() throws IOException {
132+
SwitchBotDeviceApi spyDeviceApi = spy(deviceApi);
133+
doReturn(Collections.emptyList()).when(spyDeviceApi).getDevices();
134+
135+
String result = spyDeviceApi.getDeviceNameFromId("any-device");
136+
assertEquals("any-device", result);
137+
}
138+
139+
@Test
140+
public void testConcurrentCacheRefresh() throws InterruptedException {
141+
SwitchBotDeviceApi spyDeviceApi = spy(deviceApi);
142+
spyDeviceApi.deviceIdToNamesCacheTime = System.currentTimeMillis() - (ITimeConstants.HOUR * 2);
143+
144+
Device device = new Device();
145+
device.setDeviceId("concurrent-device");
146+
device.setDeviceName("Concurrent Test");
147+
try {
148+
doReturn(Arrays.asList(device)).when(spyDeviceApi).getDevices();
149+
} catch (IOException e) {
150+
fail("Setup failed: " + e.getMessage());
151+
}
152+
153+
Thread thread1 = new Thread(() -> {
154+
spyDeviceApi.getDeviceNameFromId("concurrent-device");
155+
});
156+
157+
Thread thread2 = new Thread(() -> {
158+
spyDeviceApi.getDeviceNameFromId("concurrent-device");
159+
});
160+
161+
thread1.start();
162+
thread2.start();
163+
164+
thread1.join();
165+
thread2.join();
166+
167+
try {
168+
verify(spyDeviceApi, atLeastOnce()).getDevices();
169+
} catch (IOException e) {
170+
fail("Verification failed: " + e.getMessage());
171+
}
172+
}
173+
}

0 commit comments

Comments
 (0)