View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.commons.function;
18  
19  import static org.junit.jupiter.api.Assertions.*;
20  
21  import java.util.concurrent.atomic.AtomicInteger;
22  
23  import org.apache.juneau.*;
24  import org.junit.jupiter.api.*;
25  
26  class ThrowingConsumer2_Test extends TestBase {
27  
28  	//------------------------------------------------------------------------------------------------------------------
29  	// Basic tests.
30  	//------------------------------------------------------------------------------------------------------------------
31  	@Test void a01_basic() {
32  		var callCount = new AtomicInteger();
33  		var receivedValues = new Object[2];
34  
35  		var consumer = (ThrowingConsumer2<String, Integer>)(a, b) -> {
36  			callCount.incrementAndGet();
37  			receivedValues[0] = a;
38  			receivedValues[1] = b;
39  		};
40  
41  		consumer.apply("test", 42);
42  		assertEquals(1, callCount.get());
43  		assertEquals("test", receivedValues[0]);
44  		assertEquals(42, receivedValues[1]);
45  	}
46  
47  	@Test void a02_withNullValues() {
48  		var callCount = new AtomicInteger();
49  		var receivedValues = new Object[2];
50  
51  		var consumer = (ThrowingConsumer2<String, Integer>)(a, b) -> {
52  			callCount.incrementAndGet();
53  			receivedValues[0] = a;
54  			receivedValues[1] = b;
55  		};
56  
57  		consumer.apply(null, null);
58  		assertEquals(1, callCount.get());
59  		assertNull(receivedValues[0]);
60  		assertNull(receivedValues[1]);
61  	}
62  
63  	//------------------------------------------------------------------------------------------------------------------
64  	// Exception handling tests.
65  	//------------------------------------------------------------------------------------------------------------------
66  	@Test void b01_throwsCheckedException() {
67  		var consumer = (ThrowingConsumer2<String, Integer>)(a, b) -> {
68  			throw new Exception("Test exception");
69  		};
70  
71  		var ex = assertThrows(RuntimeException.class, () -> {
72  			consumer.apply("test", 42);
73  		});
74  
75  		assertTrue(ex.getCause() instanceof Exception);
76  		assertEquals("Test exception", ex.getCause().getMessage());
77  	}
78  
79  	@Test void b02_throwsRuntimeException() {
80  		var consumer = (ThrowingConsumer2<String, Integer>)(a, b) -> {
81  			throw new RuntimeException("Test runtime exception");
82  		};
83  
84  		var ex = assertThrows(RuntimeException.class, () -> {
85  			consumer.apply("test", 42);
86  		});
87  
88  		// RuntimeExceptions should be re-thrown as-is (not wrapped)
89  		assertEquals("Test runtime exception", ex.getMessage());
90  		assertNull(ex.getCause());
91  	}
92  
93  	@Test void b03_throwsError() {
94  		var consumer = (ThrowingConsumer2<String, Integer>)(a, b) -> {
95  			throw new Error("Test error");
96  		};
97  
98  		// Error is not an Exception, so it's not caught and propagates directly
99  		var ex = assertThrows(Error.class, () -> {
100 			consumer.apply("test", 42);
101 		});
102 
103 		assertEquals("Test error", ex.getMessage());
104 	}
105 
106 	//------------------------------------------------------------------------------------------------------------------
107 	// Functional interface tests.
108 	//------------------------------------------------------------------------------------------------------------------
109 	@Test void c01_usedAsConsumer2() {
110 		var callCount = new AtomicInteger();
111 
112 		// ThrowingConsumer2 extends Consumer2, so it can be used where Consumer2 is expected
113 		var consumer = (Consumer2<String, Integer>)(a, b) -> {
114 			callCount.incrementAndGet();
115 		};
116 
117 		consumer.apply("test", 42);
118 		assertEquals(1, callCount.get());
119 	}
120 
121 	@Test void c02_lambdaExpression() {
122 		var sum = new AtomicInteger(0);
123 
124 		var consumer = (ThrowingConsumer2<Integer, Integer>)(a, b) -> {
125 			sum.addAndGet(a + b);
126 		};
127 
128 		consumer.apply(5, 10);
129 		consumer.apply(3, 7);
130 		assertEquals(25, sum.get());
131 	}
132 
133 	@Test void c03_methodReference() {
134 		var map = new java.util.HashMap<String, Integer>();
135 
136 		var consumer = (ThrowingConsumer2<String, Integer>)map::put;
137 
138 		consumer.apply("key1", 1);
139 		consumer.apply("key2", 2);
140 		assertEquals(2, map.size());
141 		assertEquals(1, map.get("key1"));
142 		assertEquals(2, map.get("key2"));
143 	}
144 
145 	@Test void c04_andThen() {
146 		var callCount1 = new AtomicInteger();
147 		var callCount2 = new AtomicInteger();
148 
149 		var consumer1 = (ThrowingConsumer2<String, Integer>)(a, b) -> callCount1.incrementAndGet();
150 		var consumer2 = (ThrowingConsumer2<String, Integer>)(a, b) -> callCount2.incrementAndGet();
151 
152 		var composed = consumer1.andThen(consumer2);
153 		composed.apply("test", 42);
154 
155 		assertEquals(1, callCount1.get());
156 		assertEquals(1, callCount2.get());
157 	}
158 
159 	@Test void c05_andThen_withException() {
160 		var callCount = new AtomicInteger();
161 
162 		var consumer1 = (ThrowingConsumer2<String, Integer>)(a, b) -> {
163 			throw new RuntimeException("First consumer failed");
164 		};
165 		var consumer2 = (ThrowingConsumer2<String, Integer>)(a, b) -> callCount.incrementAndGet();
166 
167 		var composed = consumer1.andThen(consumer2);
168 
169 		var ex = assertThrows(RuntimeException.class, () -> {
170 			composed.apply("test", 42);
171 		});
172 
173 		assertEquals("First consumer failed", ex.getMessage());
174 		assertEquals(0, callCount.get()); // Second consumer should not be called
175 	}
176 }
177