Skip to content

Commit 7c9e461

Browse files
committed
build: unit test for routerimpl, arrayvalue and hashvalue
1 parent 8cb7fa1 commit 7c9e461

4 files changed

Lines changed: 681 additions & 4 deletions

File tree

jooby/src/main/java/io/jooby/internal/RouterImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -885,8 +885,8 @@ private void putPredicate(Predicate<Context> predicate, Chi tree) {
885885
}
886886

887887
private void removePreDispatchInitializer(ContextInitializer initializer) {
888-
if (this.preDispatchInitializer instanceof ContextInitializerList) {
889-
((ContextInitializerList) initializer).remove(initializer);
888+
if (this.preDispatchInitializer instanceof ContextInitializerList initializers) {
889+
initializers.remove(initializer);
890890
} else if (this.preDispatchInitializer == initializer) {
891891
this.preDispatchInitializer = null;
892892
}
@@ -904,8 +904,8 @@ private void addPreDispatchInitializer(ContextInitializer initializer) {
904904
}
905905

906906
private void removePostDispatchInitializer(ContextInitializer initializer) {
907-
if (this.postDispatchInitializer instanceof ContextInitializerList) {
908-
((ContextInitializerList) postDispatchInitializer).remove(initializer);
907+
if (this.postDispatchInitializer instanceof ContextInitializerList initializerList) {
908+
initializerList.remove(initializer);
909909
} else if (this.postDispatchInitializer == initializer) {
910910
this.postDispatchInitializer = null;
911911
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package io.jooby.internal;
7+
8+
import static org.junit.jupiter.api.Assertions.*;
9+
import static org.mockito.ArgumentMatchers.any;
10+
import static org.mockito.Mockito.mock;
11+
import static org.mockito.Mockito.when;
12+
13+
import java.util.List;
14+
import java.util.Map;
15+
import java.util.Optional;
16+
import java.util.Set;
17+
18+
import org.junit.jupiter.api.BeforeEach;
19+
import org.junit.jupiter.api.DisplayName;
20+
import org.junit.jupiter.api.Test;
21+
22+
import io.jooby.exception.MissingValueException;
23+
import io.jooby.exception.TypeMismatchException;
24+
import io.jooby.value.Value;
25+
import io.jooby.value.ValueFactory;
26+
27+
public class ArrayValueTest {
28+
29+
private ValueFactory factory;
30+
31+
@BeforeEach
32+
void setUp() {
33+
factory = new ValueFactory();
34+
}
35+
36+
@Test
37+
@DisplayName("Test basic accessors, add variants, and iterator")
38+
void basicOperations() {
39+
ArrayValue array = new ArrayValue(factory, "tags");
40+
41+
// Add variants
42+
array.add("java"); // String
43+
array.add(List.of("kotlin", "scala")); // List<String>
44+
array.add(Value.value(factory, "tags", "groovy")); // Value
45+
46+
assertEquals("tags", array.name());
47+
assertEquals(4, array.size());
48+
assertTrue(array.toString().contains("java"));
49+
assertTrue(array.iterator().hasNext());
50+
}
51+
52+
@Test
53+
@DisplayName("Test get(int), get(String), and getOrDefault branches")
54+
void getOperations() {
55+
ArrayValue array = new ArrayValue(factory, "tags").add(List.of("a", "b"));
56+
57+
// Valid index
58+
assertEquals("a", array.get(0).value());
59+
60+
// Invalid index (catches IndexOutOfBoundsException -> returns MissingValue)
61+
Value missingIndex = array.get(5);
62+
assertTrue(missingIndex.isMissing());
63+
assertEquals("tags[5]", missingIndex.name());
64+
65+
// Object lookup on an array (always returns MissingValue)
66+
Value missingObject = array.get("prop");
67+
assertTrue(missingObject.isMissing());
68+
assertEquals("tags.prop", missingObject.name());
69+
70+
// getOrDefault
71+
assertEquals("defaultProp", array.getOrDefault("prop", "defaultProp").value());
72+
}
73+
74+
@Test
75+
@DisplayName("Test value() evaluation and ternary branch for null name")
76+
void valueEvaluation() {
77+
// Standard name branch
78+
ArrayValue array = new ArrayValue(factory, "tags");
79+
assertThrows(TypeMismatchException.class, array::value);
80+
81+
// Null name branch (triggers fallback to getClass().getSimpleName())
82+
ArrayValue unnamedArray = new ArrayValue(factory, null);
83+
assertThrows(TypeMismatchException.class, unnamedArray::value);
84+
}
85+
86+
@Test
87+
@DisplayName("Test Type Conversions: to, toNullable, toOptional")
88+
void typeConversions() {
89+
ArrayValue array = new ArrayValue(factory, "nums").add(List.of("1", "2"));
90+
91+
// to(Class)
92+
assertEquals(1, array.to(Integer.class));
93+
94+
// toNullable(Class) - Empty branch vs Populated branch
95+
ArrayValue emptyArray = new ArrayValue(factory, "empty");
96+
assertNull(emptyArray.toNullable(Integer.class));
97+
assertEquals(1, array.toNullable(Integer.class));
98+
99+
// toOptional(Class) - Happy path
100+
assertEquals(Optional.of(1), array.toOptional(Integer.class));
101+
102+
// toOptional(Class) - Exception path (catches MissingValueException)
103+
ValueFactory mockFactory = mock(ValueFactory.class);
104+
when(mockFactory.convert(any(), any(), any())).thenThrow(new MissingValueException("mock"));
105+
ArrayValue exceptionArray = new ArrayValue(mockFactory, "err").add("1");
106+
107+
assertEquals(Optional.empty(), exceptionArray.toOptional(Integer.class));
108+
}
109+
110+
@Test
111+
@DisplayName("Test toList() switch optimizations (sizes 0, 1, 2, 3, default)")
112+
void toListSwitchOptimizations() {
113+
ArrayValue a0 = new ArrayValue(factory, "a0");
114+
assertEquals(List.of(), a0.toList());
115+
116+
ArrayValue a1 = new ArrayValue(factory, "a1").add("1");
117+
assertEquals(List.of("1"), a1.toList());
118+
119+
ArrayValue a2 = new ArrayValue(factory, "a2").add(List.of("1", "2"));
120+
assertEquals(List.of("1", "2"), a2.toList());
121+
122+
ArrayValue a3 = new ArrayValue(factory, "a3").add(List.of("1", "2", "3"));
123+
assertEquals(List.of("1", "2", "3"), a3.toList());
124+
125+
ArrayValue a4 = new ArrayValue(factory, "a4").add(List.of("1", "2", "3", "4"));
126+
assertEquals(List.of("1", "2", "3", "4"), a4.toList()); // Hits 'default' -> collect()
127+
}
128+
129+
@Test
130+
@DisplayName("Test toSet() switch optimizations (sizes 0, 1, default)")
131+
void toSetSwitchOptimizations() {
132+
ArrayValue a0 = new ArrayValue(factory, "a0");
133+
assertEquals(Set.of(), a0.toSet());
134+
135+
ArrayValue a1 = new ArrayValue(factory, "a1").add("1");
136+
assertEquals(Set.of("1"), a1.toSet());
137+
138+
ArrayValue a2 = new ArrayValue(factory, "a2").add(List.of("1", "2"));
139+
assertEquals(Set.of("1", "2"), a2.toSet()); // Hits 'default' -> collect()
140+
}
141+
142+
@Test
143+
@DisplayName("Test Typed Collections and the collect() method branches")
144+
void typedCollectionsAndCollect() {
145+
ArrayValue array = new ArrayValue(factory, "nums").add(List.of("1", "2", "1"));
146+
147+
// String.class branch inside collect()
148+
assertEquals(List.of("1", "2", "1"), array.toList(String.class));
149+
assertEquals(Set.of("1", "2"), array.toSet(String.class));
150+
151+
// Non-String.class branch inside collect() (triggers ValueFactory conversion)
152+
assertEquals(List.of(1, 2, 1), array.toList(Integer.class));
153+
assertEquals(Set.of(1, 2), array.toSet(Integer.class));
154+
}
155+
156+
@Test
157+
@DisplayName("Test toMultimap aggregation")
158+
void toMultimap() {
159+
ArrayValue array = new ArrayValue(factory, "multi").add(List.of("a", "b"));
160+
161+
Map<String, List<String>> multimap = array.toMultimap();
162+
assertEquals(1, multimap.size());
163+
assertEquals(List.of("a", "b"), multimap.get("multi"));
164+
}
165+
}

0 commit comments

Comments
 (0)