|
1 | 1 | package com.fasterxml.jackson.databind.deser.lazy;
|
2 | 2 |
|
| 3 | +import java.math.BigDecimal; |
| 4 | + |
| 5 | +import org.mockito.MockedStatic; |
| 6 | +import org.mockito.Mockito; |
| 7 | + |
3 | 8 | import com.fasterxml.jackson.annotation.JsonCreator;
|
4 | 9 | import com.fasterxml.jackson.annotation.JsonProperty;
|
5 | 10 | import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
6 | 11 | import com.fasterxml.jackson.core.io.NumberInput;
|
7 |
| - |
8 |
| -import com.fasterxml.jackson.databind.BaseMapTest; |
9 |
| -import com.fasterxml.jackson.databind.DatabindException; |
10 |
| -import com.fasterxml.jackson.databind.DeserializationFeature; |
11 |
| -import com.fasterxml.jackson.databind.ObjectMapper; |
12 |
| -import com.fasterxml.jackson.databind.ObjectReader; |
| 12 | +import com.fasterxml.jackson.databind.*; |
13 | 13 | import com.fasterxml.jackson.databind.json.JsonMapper;
|
14 | 14 |
|
15 |
| -import org.junit.Ignore; |
16 |
| -import org.junit.runner.RunWith; |
17 |
| -import org.mockito.Mockito; |
18 |
| -import org.powermock.core.classloader.annotations.PrepareForTest; |
19 |
| -import org.powermock.modules.junit4.PowerMockRunner; |
20 |
| - |
21 |
| -import static org.powermock.api.mockito.PowerMockito.*; |
22 |
| - |
23 |
| -import java.math.BigDecimal; |
| 15 | +import static org.mockito.Mockito.mockStatic; |
24 | 16 |
|
25 | 17 | /**
|
26 | 18 | * Tests to verify that skipping of unknown/unmapped works such that
|
27 | 19 | * "expensive" numbers (all floating-point, {@code BigInteger}) is avoided.
|
28 | 20 | */
|
29 |
| -@RunWith(PowerMockRunner.class) |
30 |
| -@PrepareForTest(fullyQualifiedNames = "com.fasterxml.jackson.core.io.NumberInput") |
31 |
| -@Ignore("Powermock stopped working with NumberUtil refactoring see [databind#4250]") |
32 | 21 | public class LazyIgnoralForNumbers3730Test extends BaseMapTest
|
33 | 22 | {
|
34 | 23 | static class ExtractFieldsNoDefaultConstructor3730 {
|
@@ -103,103 +92,115 @@ static class Values {
|
103 | 92 |
|
104 | 93 | public void testIgnoreBigInteger() throws Exception
|
105 | 94 | {
|
106 |
| - final String MOCK_MSG = "mock: deliberate failure for parseBigInteger"; |
107 |
| - mockStatic(NumberInput.class); |
108 |
| - when(NumberInput.parseBigInteger(Mockito.anyString())) |
109 |
| - .thenThrow(new IllegalStateException(MOCK_MSG)); |
110 |
| - when(NumberInput.parseBigInteger(Mockito.anyString(), Mockito.anyBoolean())) |
111 |
| - .thenThrow(new IllegalStateException(MOCK_MSG)); |
112 |
| - StringBuilder stringBuilder = new StringBuilder(); |
113 |
| - for (int i = 0; i < 999; i++) { |
114 |
| - stringBuilder.append(7); |
115 |
| - } |
116 |
| - final String testBigInteger = stringBuilder.toString(); |
117 |
| - final String json = genJson(testBigInteger); |
118 |
| - ExtractFieldsNoDefaultConstructor3730 ef = |
119 |
| - MAPPER.readValue(json, ExtractFieldsNoDefaultConstructor3730.class); |
120 |
| - assertNotNull(ef); |
121 |
| - // Ok but then let's ensure method IS called, if field is actually mapped, |
122 |
| - // first to Number |
123 |
| - try { |
124 |
| - Object ob = STRICT_MAPPER.readValue(json, UnwrappedWithNumber.class); |
125 |
| - fail("Should throw exception with mocking: instead got: "+MAPPER.writeValueAsString(ob)); |
126 |
| - } catch (DatabindException e) { |
127 |
| - verifyMockException(e, MOCK_MSG); |
| 95 | + try (MockedStatic<NumberInput> mocked = mockStatic(NumberInput.class)) { |
| 96 | + // Set up, mock NumberInput.parseBigInteger() to throw exception |
| 97 | + final String MOCK_MSG = "mock: deliberate failure for parseBigInteger"; |
| 98 | + mocked.when(() -> NumberInput.parseBigInteger(Mockito.anyString())) |
| 99 | + .thenThrow(new IllegalStateException(MOCK_MSG)); |
| 100 | + mocked.when(() -> NumberInput.parseBigInteger(Mockito.anyString(), Mockito.anyBoolean())) |
| 101 | + .thenThrow(new IllegalStateException(MOCK_MSG)); |
| 102 | + |
| 103 | + // Then start testing! |
| 104 | + StringBuilder stringBuilder = new StringBuilder(); |
| 105 | + for (int i = 0; i < 999; i++) { |
| 106 | + stringBuilder.append(7); |
| 107 | + } |
| 108 | + final String testBigInteger = stringBuilder.toString(); |
| 109 | + final String json = genJson(testBigInteger); |
| 110 | + ExtractFieldsNoDefaultConstructor3730 ef = |
| 111 | + MAPPER.readValue(json, ExtractFieldsNoDefaultConstructor3730.class); |
| 112 | + assertNotNull(ef); |
| 113 | + // Ok but then let's ensure method IS called, if field is actually mapped, |
| 114 | + // first to Number |
| 115 | + try { |
| 116 | + Object ob = STRICT_MAPPER.readValue(json, UnwrappedWithNumber.class); |
| 117 | + fail("Should throw exception with mocking: instead got: "+MAPPER.writeValueAsString(ob)); |
| 118 | + } catch (DatabindException e) { |
| 119 | + verifyMockException(e, MOCK_MSG); |
| 120 | + } |
128 | 121 | }
|
129 | 122 | }
|
130 | 123 |
|
131 | 124 | public void testIgnoreFPValuesDefault() throws Exception
|
132 | 125 | {
|
133 |
| - final String MOCK_MSG = "mock: deliberate failure for parseDouble"; |
134 |
| - // With default settings we would parse Doubles, so check |
135 |
| - mockStatic(NumberInput.class); |
136 |
| - when(NumberInput.parseDouble(Mockito.anyString())) |
| 126 | + try (MockedStatic<NumberInput> mocked = mockStatic(NumberInput.class)) { |
| 127 | + // Set up, mock NumberInput.parseDouble() to throw exception |
| 128 | + final String MOCK_MSG = "mock: deliberate failure for parseDouble"; |
| 129 | + // With default settings we would parse Doubles, so check |
| 130 | + mocked.when(() -> NumberInput.parseDouble(Mockito.anyString())) |
137 | 131 | .thenThrow(new IllegalStateException(MOCK_MSG));
|
138 |
| - when(NumberInput.parseDouble(Mockito.anyString(), Mockito.anyBoolean())) |
| 132 | + mocked.when(() -> NumberInput.parseDouble(Mockito.anyString(), Mockito.anyBoolean())) |
139 | 133 | .thenThrow(new IllegalStateException(MOCK_MSG));
|
140 |
| - final String json = genJson("0.25"); |
141 |
| - ExtractFieldsNoDefaultConstructor3730 ef = |
142 |
| - MAPPER.readValue(json, ExtractFieldsNoDefaultConstructor3730.class); |
143 |
| - assertNotNull(ef); |
144 |
| - |
145 |
| - // Ok but then let's ensure method IS called, if field is actually mapped |
146 |
| - // First, to "Number" |
147 |
| - try { |
148 |
| - STRICT_MAPPER.readValue(json, UnwrappedWithNumber.class); |
149 |
| - fail("Should throw exception with mocking!"); |
150 |
| - } catch (DatabindException e) { |
151 |
| - verifyMockException(e, MOCK_MSG); |
152 |
| - } |
153 | 134 |
|
154 |
| - // And then to "double" |
155 |
| - // 01-Feb-2023, tatu: Not quite working, yet: |
156 |
| - try { |
157 |
| - STRICT_MAPPER.readValue(json, UnwrappedWithDouble.class); |
158 |
| - fail("Should throw exception with mocking!"); |
159 |
| - } catch (DatabindException e) { |
160 |
| - e.printStackTrace(); |
161 |
| - verifyMockException(e, MOCK_MSG); |
| 135 | + // Then start testing! |
| 136 | + final String json = genJson("0.25"); |
| 137 | + ExtractFieldsNoDefaultConstructor3730 ef = |
| 138 | + MAPPER.readValue(json, ExtractFieldsNoDefaultConstructor3730.class); |
| 139 | + assertNotNull(ef); |
| 140 | + |
| 141 | + // Ok but then let's ensure method IS called, if field is actually mapped |
| 142 | + // First, to "Number" |
| 143 | + try { |
| 144 | + STRICT_MAPPER.readValue(json, UnwrappedWithNumber.class); |
| 145 | + fail("Should throw exception with mocking!"); |
| 146 | + } catch (DatabindException e) { |
| 147 | + verifyMockException(e, MOCK_MSG); |
| 148 | + } |
| 149 | + |
| 150 | + // And then to "double" |
| 151 | + // 01-Feb-2023, tatu: Not quite working, yet: |
| 152 | + try { |
| 153 | + STRICT_MAPPER.readValue(json, UnwrappedWithDouble.class); |
| 154 | + fail("Should throw exception with mocking!"); |
| 155 | + } catch (DatabindException e) { |
| 156 | + e.printStackTrace(); |
| 157 | + verifyMockException(e, MOCK_MSG); |
| 158 | + } |
162 | 159 | }
|
163 | 160 | }
|
164 | 161 |
|
165 | 162 | public void testIgnoreFPValuesBigDecimal() throws Exception
|
166 | 163 | {
|
167 |
| - final String MOCK_MSG = "mock: deliberate failure for parseBigDecimal"; |
168 |
| - ObjectReader reader = MAPPER |
169 |
| - .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) |
170 |
| - .readerFor(ExtractFieldsNoDefaultConstructor3730.class); |
171 |
| - |
172 |
| - // Now should get calls to `parseBigDecimal`... eventually |
173 |
| - mockStatic(NumberInput.class); |
174 |
| - when(NumberInput.parseBigDecimal(Mockito.anyString())) |
| 164 | + try (MockedStatic<NumberInput> mock = mockStatic(NumberInput.class)) { |
| 165 | + // Set up, mock NumberInput.parseBigDecimal() to throw exception |
| 166 | + // Now should get calls to `parseBigDecimal`... eventually |
| 167 | + final String MOCK_MSG = "mock: deliberate failure for parseBigDecimal"; |
| 168 | + // With default settings we would parse Doubles, so check |
| 169 | + mock.when(() -> NumberInput.parseBigDecimal(Mockito.anyString())) |
175 | 170 | .thenThrow(new IllegalStateException(MOCK_MSG));
|
176 |
| - when(NumberInput.parseBigDecimal(Mockito.anyString(), Mockito.anyBoolean())) |
| 171 | + mock.when(() -> NumberInput.parseBigDecimal(Mockito.anyString(), Mockito.anyBoolean())) |
177 | 172 | .thenThrow(new IllegalStateException(MOCK_MSG));
|
178 | 173 |
|
179 |
| - final String json = genJson("0.25"); |
180 |
| - ExtractFieldsNoDefaultConstructor3730 ef = |
181 |
| - reader.readValue(genJson(json)); |
182 |
| - assertNotNull(ef); |
183 |
| - |
184 |
| - // But then ensure we'll fail with unknown (except does it work with unwrapped?) |
185 |
| - reader = reader.with(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); |
186 |
| - |
187 |
| - // Ok but then let's ensure method IS called, if field is actually mapped |
188 |
| - // First to Number |
189 |
| - try { |
190 |
| - reader.forType(UnwrappedWithNumber.class).readValue(json); |
191 |
| - fail("Should throw exception with mocking!"); |
192 |
| - } catch (DatabindException e) { |
193 |
| - verifyMockException(e, MOCK_MSG); |
194 |
| - } |
195 |
| - |
196 |
| - // And then to "BigDecimal" |
197 |
| - // 01-Feb-2023, tatu: Not quite working, yet: |
198 |
| - try { |
199 |
| - reader.forType(UnwrappedWithBigDecimal.class).readValue(json); |
200 |
| - fail("Should throw exception with mocking!"); |
201 |
| - } catch (DatabindException e) { |
202 |
| - verifyMockException(e, MOCK_MSG); |
| 174 | + // Then start testing! |
| 175 | + ObjectReader reader = MAPPER |
| 176 | + .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) |
| 177 | + .readerFor(ExtractFieldsNoDefaultConstructor3730.class); |
| 178 | + |
| 179 | + final String json = genJson("0.25"); |
| 180 | + ExtractFieldsNoDefaultConstructor3730 ef = |
| 181 | + reader.readValue(genJson(json)); |
| 182 | + assertNotNull(ef); |
| 183 | + |
| 184 | + // But then ensure we'll fail with unknown (except does it work with unwrapped?) |
| 185 | + reader = reader.with(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); |
| 186 | + |
| 187 | + // Ok but then let's ensure method IS called, if field is actually mapped |
| 188 | + // First to Number |
| 189 | + try { |
| 190 | + reader.forType(UnwrappedWithNumber.class).readValue(json); |
| 191 | + fail("Should throw exception with mocking!"); |
| 192 | + } catch (DatabindException e) { |
| 193 | + verifyMockException(e, MOCK_MSG); |
| 194 | + } |
| 195 | + |
| 196 | + // And then to "BigDecimal" |
| 197 | + // 01-Feb-2023, tatu: Not quite working, yet: |
| 198 | + try { |
| 199 | + reader.forType(UnwrappedWithBigDecimal.class).readValue(json); |
| 200 | + fail("Should throw exception with mocking!"); |
| 201 | + } catch (DatabindException e) { |
| 202 | + verifyMockException(e, MOCK_MSG); |
| 203 | + } |
203 | 204 | }
|
204 | 205 | }
|
205 | 206 |
|
|
0 commit comments