Skip to content

Commit b71478e

Browse files
authored
Add Java 1.8 test examples (#8)
* TestUtils for System.out management * Lambda Expression * Functional Interfaces * Default and Static Methods in Interfaces * Optional Class * Method References * Streams API * New Date and Time API
1 parent 3759d19 commit b71478e

File tree

4 files changed

+279
-8
lines changed

4 files changed

+279
-8
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ This project includes unit tests for key functionalities introduced in each Java
1919
- [Java 1.5 (Java 5)](src/test/java/pl/mperor/lab/java/Java5.java)
2020
- [Java 1.6 (Java 6)](src/test/java/pl/mperor/lab/java/Java6.java)
2121
- [Java 1.7 (Java 7)](src/test/java/pl/mperor/lab/java/Java7.java)
22+
- [Java 1.8 (Java 8)](src/test/java/pl/mperor/lab/java/Java8.java)
2223

2324
For detailed examples and tests of each feature, please refer to the individual source files linked above.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package pl.mperor.lab;
2+
3+
import java.io.*;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
import java.util.NoSuchElementException;
7+
import java.util.stream.Collectors;
8+
9+
public class TestUtils {
10+
11+
private static final PrintStream ORIGINAL = System.out;
12+
13+
public static ReadableOut setTempSystemOut() {
14+
var temp = new ByteArrayOutputStream();
15+
System.setOut(new PrintStream(temp));
16+
return new ReadableOut(temp);
17+
}
18+
19+
public static void resetSystemOut() {
20+
System.setOut(ORIGINAL);
21+
}
22+
23+
public record ReadableOut(ByteArrayOutputStream out) {
24+
25+
public String all() {
26+
return out.toString();
27+
}
28+
29+
public TestList<String> lines() {
30+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(out.toByteArray())))) {
31+
return reader.lines().collect(Collectors.toCollection(TestArrayList::new));
32+
} catch (IOException e) {
33+
throw new RuntimeException(e);
34+
}
35+
}
36+
}
37+
38+
public static class TestArrayList<E> extends ArrayList<E> implements TestList<E> {
39+
}
40+
41+
public interface TestList<E> extends List<E> {
42+
default E getSecond() {
43+
return getNext(1);
44+
}
45+
46+
default E getThird() {
47+
return getNext(2);
48+
}
49+
50+
private E getNext(int id) {
51+
if (this.isEmpty()) {
52+
throw new NoSuchElementException();
53+
} else {
54+
return this.get(id);
55+
}
56+
}
57+
}
58+
59+
}

src/test/java/pl/mperor/lab/java/Java5.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
import org.junit.jupiter.api.Assertions;
44
import org.junit.jupiter.api.Test;
5+
import pl.mperor.lab.TestUtils;
56
import pl.mperor.lab.java.generic.Box;
67

7-
import java.io.ByteArrayOutputStream;
8-
import java.io.PrintStream;
98
import java.lang.annotation.*;
109
import java.lang.reflect.Method;
1110
import java.util.Arrays;
@@ -102,19 +101,16 @@ public void testAnnotation() throws NoSuchMethodException {
102101
@Test
103102
public void testConcurrencyAPI() {
104103
ExecutorService executor = Executors.newSingleThreadExecutor();
105-
var original = System.out;
106-
var out = new ByteArrayOutputStream();
107-
System.setOut(new PrintStream(out));
108-
104+
var out = TestUtils.setTempSystemOut();
109105
IntStream.rangeClosed(1, 3).forEach(i ->
110106
executor.submit(() -> {
111107
// Code executed in a separate thread
112108
System.out.printf("Task %d ", i);
113109
})
114110
);
115111
executor.close();
116-
Assertions.assertEquals("Task 1 Task 2 Task 3 ", out.toString());
117-
System.setOut(original);
112+
Assertions.assertEquals("Task 1 Task 2 Task 3 ", out.all());
113+
TestUtils.resetSystemOut();
118114
}
119115

120116
@Test
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
package pl.mperor.lab.java;
2+
3+
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.Test;
6+
import pl.mperor.lab.TestUtils;
7+
8+
import java.lang.reflect.Method;
9+
import java.lang.reflect.Modifier;
10+
import java.time.*;
11+
import java.util.*;
12+
import java.util.function.*;
13+
import java.util.stream.Collectors;
14+
import java.util.stream.IntStream;
15+
import java.util.stream.Stream;
16+
17+
/**
18+
* Java 1.8 (March 2014)
19+
*/
20+
public class Java8 {
21+
22+
@Test
23+
public void testLambdaExpression() {
24+
var out = TestUtils.setTempSystemOut();
25+
Runnable anonymousInnerClass = new Runnable() {
26+
@Override
27+
public void run() {
28+
System.out.println("Hello World from anonymous inner class!");
29+
}
30+
};
31+
Runnable lambdaExpression = () -> System.out.println("Hello World from Lambda!");
32+
33+
anonymousInnerClass.run();
34+
lambdaExpression.run();
35+
36+
Assertions.assertEquals("Hello World from anonymous inner class!", out.lines().getFirst());
37+
Assertions.assertEquals("Hello World from Lambda!", out.lines().getSecond());
38+
39+
Assertions.assertInstanceOf(Runnable.class, anonymousInnerClass);
40+
Assertions.assertInstanceOf(Runnable.class, lambdaExpression);
41+
TestUtils.resetSystemOut();
42+
}
43+
44+
@Test
45+
public void testCoreFunctionalInterfaces() {
46+
Predicate<?> nullValidator = Objects::isNull;
47+
Assertions.assertTrue(nullValidator.test(null));
48+
49+
var out = TestUtils.setTempSystemOut();
50+
Consumer<String> systemPrinter = System.out::print;
51+
systemPrinter.accept("printed");
52+
Assertions.assertEquals("printed", out.all());
53+
TestUtils.resetSystemOut();
54+
55+
Supplier<Double> randomGenerator = Math::random;
56+
Double random = randomGenerator.get();
57+
Assertions.assertTrue(random >= 0.0 && random < 1.0);
58+
59+
UnaryOperator<Integer> absoluteUpdater = Math::abs;
60+
Assertions.assertEquals(1, absoluteUpdater.apply(-1));
61+
62+
Function<String, Integer> numberParser = Integer::parseInt;
63+
Assertions.assertEquals(1, numberParser.apply("1"));
64+
}
65+
66+
@Test
67+
public void testCustomFunctionalInterface() {
68+
Testable testable = () -> {
69+
};
70+
testable.test();
71+
// same as Runnable runnable = () -> {};
72+
73+
assertFunctionalInterface(Testable.class);
74+
}
75+
76+
private static void assertFunctionalInterface(Class<?> clazz) {
77+
if (!clazz.isInterface()) {
78+
Assertions.fail("Clazz is not an interface!");
79+
}
80+
81+
long abstractMethodCount = Arrays.stream(clazz.getMethods())
82+
.map(Method::getModifiers)
83+
.filter(Modifier::isAbstract)
84+
.count();
85+
86+
Assertions.assertTrue(clazz.isAnnotationPresent(FunctionalInterface.class) || 1 == abstractMethodCount,
87+
"Functional interface should contain exactly one abstract method, but @FunctionalInterface is optional!");
88+
}
89+
90+
@FunctionalInterface
91+
public interface Testable {
92+
void test();
93+
}
94+
95+
@Test
96+
public void testDefaultAndStaticMethodsInInterface() throws NoSuchMethodException {
97+
Tester tester = () -> new Testable[]{
98+
() -> System.out.println("First test"),
99+
() -> System.out.println("Second test"),
100+
};
101+
var out = TestUtils.setTempSystemOut();
102+
tester.run();
103+
Assertions.assertEquals("First test", out.lines().getFirst());
104+
Assertions.assertEquals("Second test", out.lines().getSecond());
105+
TestUtils.resetSystemOut();
106+
107+
Method defaultMethod = Tester.class.getMethod("run");
108+
Assertions.assertTrue(defaultMethod.isDefault());
109+
110+
Method staticMethod = Tester.class.getMethod("checkAll", Testable[].class);
111+
Assertions.assertTrue(Modifier.isStatic(staticMethod.getModifiers()));
112+
113+
assertFunctionalInterface(Tester.class);
114+
}
115+
116+
public interface Tester {
117+
118+
Testable[] getTests();
119+
120+
default void run() {
121+
checkAll(getTests());
122+
}
123+
124+
static void checkAll(Testable... testable) {
125+
Arrays.stream(testable).forEach(Testable::test);
126+
}
127+
}
128+
129+
@Test
130+
public void testOptional() {
131+
Optional<String> empty = Optional.empty();
132+
Assertions.assertTrue(empty.isEmpty());
133+
Assertions.assertThrows(NoSuchElementException.class, () -> empty.get());
134+
135+
Optional<String> filled = Optional.of("Java 8");
136+
Assertions.assertTrue(filled.isPresent());
137+
Assertions.assertEquals("Java 8", filled.get());
138+
filled.ifPresent(content -> Assertions.assertEquals("Java 8", content));
139+
}
140+
141+
@Test
142+
public void testMethodReferences() {
143+
Runnable staticMethod = Reference::staticMethod;
144+
staticMethod.run();
145+
146+
Reference instance = new Reference();
147+
Runnable particularObjectInstanceMethod = instance::instanceMethod;
148+
particularObjectInstanceMethod.run();
149+
150+
Supplier<Reference> constructorMethod = Reference::new;
151+
Assertions.assertNotNull(constructorMethod.get());
152+
153+
Consumer<Reference> arbitraryObjectInstanceMethod = Reference::instanceMethod;
154+
arbitraryObjectInstanceMethod.accept(new Reference());
155+
}
156+
157+
public class Reference {
158+
159+
public void instanceMethod() {
160+
}
161+
162+
public static void staticMethod() {
163+
}
164+
}
165+
166+
@Test
167+
public void testStreamsAPI() {
168+
// Stream Creation
169+
Assertions.assertInstanceOf(Stream.class, List.of(1, 2, 3).stream());
170+
Assertions.assertInstanceOf(IntStream.class, Arrays.stream(new int[]{1, 2, 3}));
171+
Assertions.assertInstanceOf(Stream.class, Stream.of(1, 2, 3));
172+
173+
// Intermediate Operations
174+
Stream<String> intermediateOperationPipeline = List.of("c", "b", "a", "").stream()
175+
.filter(s -> s.matches("^\\w$"))
176+
.map(String::toUpperCase)
177+
.sorted();
178+
Assertions.assertInstanceOf(Stream.class, intermediateOperationPipeline);
179+
Assertions.assertEquals("ABC", intermediateOperationPipeline.collect(Collectors.joining()));
180+
IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, intermediateOperationPipeline::count);
181+
Assertions.assertEquals("stream has already been operated upon or closed", exception.getMessage());
182+
183+
// Terminal Operations
184+
Assertions.assertEquals(3, IntStream.rangeClosed(1, 3).count());
185+
Assertions.assertEquals(6, IntStream.rangeClosed(1, 3).sum());
186+
Assertions.assertEquals(6, IntStream.rangeClosed(1, 3).reduce(1, (a, b) -> a * b));
187+
Assertions.assertEquals(List.of(1, 2, 3), IntStream.rangeClosed(1, 3).boxed().collect(Collectors.toList()));
188+
Assertions.assertEquals(OptionalInt.of(3), IntStream.rangeClosed(1, 3).max());
189+
}
190+
191+
@Test
192+
public void testNewDateAndTimeAPI() {
193+
// same as DateTimeFormatter.ISO_LOCAL_DATE.parse(...)
194+
LocalDate releaseJava8Date = LocalDate.parse("2014-03-18");
195+
Assertions.assertEquals(LocalDate.of(2014, Month.MARCH, 18), releaseJava8Date);
196+
197+
LocalTime noonTime = LocalTime.of(12, 0, 0);
198+
Assertions.assertEquals(LocalTime.NOON, noonTime);
199+
200+
// same as DateTimeFormatter.ISO_LOCAL_DATE_TIME.parse(...)
201+
LocalDateTime twoThousand = LocalDateTime.parse("2000-01-01T00:00:00");
202+
Assertions.assertEquals(LocalDateTime.of(2000, 1, 1, 0, 0, 0), twoThousand);
203+
204+
Period betweenJava1And8 = Period.between(LocalDate.of(1996, Month.JANUARY, 23), LocalDate.of(2014, Month.MARCH, 8));
205+
Assertions.assertEquals(18, betweenJava1And8.getYears());
206+
207+
Duration betweenMidnightAndNoon = Duration.between(LocalTime.MIDNIGHT, LocalTime.NOON);
208+
Assertions.assertEquals(12, betweenMidnightAndNoon.toHours());
209+
210+
Instant initialInstant = Instant.ofEpochSecond(0);
211+
Assertions.assertEquals("1970-01-01T00:00:00Z", initialInstant.toString());
212+
Assertions.assertEquals(60, initialInstant.plusSeconds(60).getEpochSecond());
213+
}
214+
215+
}

0 commit comments

Comments
 (0)