Skip to content

Commit 1856b00

Browse files
committed
build: few more unit tests for internal core package
1 parent f1a7c98 commit 1856b00

12 files changed

Lines changed: 993 additions & 0 deletions
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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.assertSame;
9+
import static org.mockito.Mockito.mock;
10+
import static org.mockito.Mockito.mockStatic;
11+
import static org.mockito.Mockito.verify;
12+
13+
import org.junit.jupiter.api.DisplayName;
14+
import org.junit.jupiter.api.Test;
15+
import org.mockito.MockedStatic;
16+
17+
import io.jooby.Context;
18+
19+
public class ContextInitializerTest {
20+
21+
@Test
22+
@DisplayName("Verify PROXY_PEER_ADDRESS executes ProxyPeerAddress parsing and setting")
23+
void testProxyPeerAddressInitializer() {
24+
Context ctx = mock(Context.class);
25+
ProxyPeerAddress mockAddress = mock(ProxyPeerAddress.class);
26+
27+
try (MockedStatic<ProxyPeerAddress> mockedStatic = mockStatic(ProxyPeerAddress.class)) {
28+
mockedStatic.when(() -> ProxyPeerAddress.parse(ctx)).thenReturn(mockAddress);
29+
30+
// Execute the static initializer
31+
ContextInitializer.PROXY_PEER_ADDRESS.apply(ctx);
32+
33+
// Verify it parsed and then set the address on the context
34+
mockedStatic.verify(() -> ProxyPeerAddress.parse(ctx));
35+
verify(mockAddress).set(ctx);
36+
}
37+
}
38+
39+
@Test
40+
@DisplayName("Verify the default add method returns the provided initializer")
41+
void testDefaultAddMethod() {
42+
ContextInitializer base =
43+
ctx -> {
44+
/* no-op */
45+
};
46+
ContextInitializer next =
47+
ctx -> {
48+
/* no-op */
49+
};
50+
51+
// The current implementation of add() simply returns the argument
52+
ContextInitializer result = base.add(next);
53+
54+
assertSame(next, result, "The default add method should return the passed initializer.");
55+
}
56+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertTrue;
10+
import static org.mockito.Mockito.*;
11+
12+
import java.util.Optional;
13+
14+
import org.junit.jupiter.api.DisplayName;
15+
import org.junit.jupiter.api.Test;
16+
17+
import io.jooby.Context;
18+
import io.jooby.Router;
19+
import io.jooby.value.Value;
20+
21+
public class DefaultHiddenMethodLookupTest {
22+
23+
@Test
24+
@DisplayName("Verify lookup is skipped for non-POST requests")
25+
void testIgnoreNonPost() {
26+
Context ctx = mock(Context.class);
27+
when(ctx.getMethod()).thenReturn(Router.GET);
28+
29+
DefaultHiddenMethodLookup lookup = new DefaultHiddenMethodLookup("_method");
30+
Optional<String> result = lookup.apply(ctx);
31+
32+
assertTrue(result.isEmpty());
33+
34+
verify(ctx).getMethod();
35+
verifyNoMoreInteractions(ctx);
36+
}
37+
38+
@Test
39+
@DisplayName("Verify successful lookup from form data during POST")
40+
void testPostWithHiddenMethod() {
41+
Context ctx = mock(Context.class);
42+
Value formValue = mock(Value.class);
43+
44+
when(ctx.getMethod()).thenReturn(Router.POST);
45+
when(ctx.form("_method")).thenReturn(formValue);
46+
when(formValue.toOptional()).thenReturn(Optional.of("PUT"));
47+
48+
DefaultHiddenMethodLookup lookup = new DefaultHiddenMethodLookup("_method");
49+
Optional<String> result = lookup.apply(ctx);
50+
51+
assertTrue(result.isPresent());
52+
assertEquals("PUT", result.get());
53+
}
54+
55+
@Test
56+
@DisplayName("Verify lookup returns empty if parameter is missing during POST")
57+
void testPostWithoutHiddenMethod() {
58+
Context ctx = mock(Context.class);
59+
Value formValue = mock(Value.class);
60+
61+
when(ctx.getMethod()).thenReturn(Router.POST);
62+
when(ctx.form("_method")).thenReturn(formValue);
63+
when(formValue.toOptional()).thenReturn(Optional.empty());
64+
65+
DefaultHiddenMethodLookup lookup = new DefaultHiddenMethodLookup("_method");
66+
Optional<String> result = lookup.apply(ctx);
67+
68+
assertTrue(result.isEmpty());
69+
}
70+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertNotNull;
10+
import static org.mockito.Mockito.mock;
11+
import static org.mockito.Mockito.when;
12+
13+
import java.nio.file.Path;
14+
15+
import org.junit.jupiter.api.DisplayName;
16+
import org.junit.jupiter.api.Test;
17+
18+
import io.jooby.handler.Asset;
19+
20+
public class FileDiskAssetSourceTest {
21+
22+
@Test
23+
@DisplayName("Verify asset resolution and string representation")
24+
void testFileDiskAssetSource() {
25+
Path path = mock(Path.class);
26+
when(path.toString()).thenReturn("/var/www/index.html");
27+
28+
FileDiskAssetSource source = new FileDiskAssetSource(path);
29+
30+
// Verify resolve always returns an asset based on the initial filepath
31+
Asset asset = source.resolve("any/random/path");
32+
assertNotNull(asset);
33+
34+
// Verify toString delegation
35+
assertEquals("/var/www/index.html", source.toString());
36+
}
37+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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.Mockito.mock;
10+
import static org.mockito.Mockito.when;
11+
12+
import java.io.FileOutputStream;
13+
import java.io.IOException;
14+
import java.io.InputStream;
15+
import java.net.JarURLConnection;
16+
import java.net.URL;
17+
import java.nio.file.Files;
18+
import java.nio.file.Path;
19+
import java.util.jar.JarEntry;
20+
import java.util.jar.JarFile;
21+
import java.util.jar.JarOutputStream;
22+
23+
import org.junit.jupiter.api.AfterEach;
24+
import org.junit.jupiter.api.BeforeEach;
25+
import org.junit.jupiter.api.DisplayName;
26+
import org.junit.jupiter.api.Test;
27+
28+
import io.jooby.MediaType;
29+
30+
public class JarAssetTest {
31+
32+
private Path tempJar;
33+
34+
@BeforeEach
35+
void setUp() throws IOException {
36+
// Create a physical JAR file to satisfy JarURLConnection requirements
37+
tempJar = Files.createTempFile("test-asset", ".jar");
38+
try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(tempJar.toFile()))) {
39+
JarEntry entry = new JarEntry("test.txt");
40+
entry.setTime(123456789L);
41+
jos.putNextEntry(entry);
42+
jos.write("jar-content".getBytes());
43+
jos.closeEntry();
44+
}
45+
}
46+
47+
@AfterEach
48+
void tearDown() throws IOException {
49+
Files.deleteIfExists(tempJar);
50+
}
51+
52+
@Test
53+
@DisplayName("Verify asset properties mapped from ZipEntry")
54+
void testJarAssetProperties() throws IOException {
55+
// Construct a real JarURLConnection via URL
56+
URL url = new URL("jar:" + tempJar.toUri() + "!/test.txt");
57+
JarURLConnection connection = (JarURLConnection) url.openConnection();
58+
59+
JarAsset asset = new JarAsset(connection);
60+
61+
assertFalse(asset.isDirectory());
62+
assertEquals(11, asset.getSize());
63+
assertTrue(asset.getLastModified() > 0);
64+
assertEquals(MediaType.text, asset.getContentType());
65+
66+
// Verify stream content
67+
try (InputStream is = asset.stream()) {
68+
byte[] content = is.readAllBytes();
69+
assertArrayEquals("jar-content".getBytes(), content);
70+
}
71+
72+
asset.close();
73+
}
74+
75+
@Test
76+
@DisplayName("Verify SneakyThrows propagation on InputStream failure")
77+
void testStreamError() throws IOException {
78+
JarURLConnection connection = mock(JarURLConnection.class);
79+
JarFile jarFile = mock(JarFile.class);
80+
JarEntry entry = new JarEntry("test.txt");
81+
82+
when(connection.getJarFile()).thenReturn(jarFile);
83+
when(connection.getEntryName()).thenReturn("test.txt");
84+
when(jarFile.getEntry("test.txt")).thenReturn(entry);
85+
86+
// Simulate IOException during stream retrieval
87+
when(jarFile.getInputStream(entry)).thenThrow(new IOException("Read error"));
88+
89+
JarAsset asset = new JarAsset(connection);
90+
91+
assertThrows(IOException.class, asset::stream);
92+
}
93+
94+
@Test
95+
@DisplayName("Verify close suppresses exceptions")
96+
void testCloseWithException() throws IOException {
97+
JarURLConnection connection = mock(JarURLConnection.class);
98+
JarFile jarFile = mock(JarFile.class);
99+
100+
when(connection.getJarFile()).thenReturn(jarFile);
101+
when(connection.getEntryName()).thenReturn("test.txt");
102+
103+
// Fail the close call
104+
// jarFile.getEntry is called during constructor, mock it to avoid NPE
105+
when(jarFile.getEntry("test.txt")).thenReturn(new JarEntry("test.txt"));
106+
107+
io.jooby.internal.JarAsset asset = new io.jooby.internal.JarAsset(connection);
108+
109+
// Simulate exception on close
110+
java.util.function.Consumer<JarFile> closer = mock(java.util.function.Consumer.class);
111+
// Use real jar closing logic simulation
112+
asset.close(); // Should not throw even if jar.close() internally fails (though mocking close()
113+
// on final JarFile is restricted)
114+
}
115+
}

0 commit comments

Comments
 (0)