1
- using System . Collections . Generic ;
1
+ using System . Collections ;
2
+ using System . Collections . Generic ;
2
3
using System . Text . Json . Serialization ;
3
4
using System . Text . Json . Serialization . Metadata ;
4
5
using SystemTextJsonPatch . Exceptions ;
6
+ using SystemTextJsonPatch . Operations ;
5
7
using Xunit ;
6
8
7
9
namespace SystemTextJsonPatch . IntegrationTests ;
@@ -130,11 +132,13 @@ private class Address
130
132
private class IntDictionary
131
133
{
132
134
public IDictionary < string , int > DictionaryOfStringToInteger { get ; } = new Dictionary < string , int > ( ) ;
135
+ public IDictionary NonGenericDictionary { get ; } = new NonGenericDictionary ( ) ;
133
136
}
134
137
135
138
private class CustomerDictionary
136
139
{
137
- public IDictionary < int , Customer > DictionaryOfStringToCustomer { get ; } = new Dictionary < int , Customer > ( ) ;
140
+ public IDictionary < int , Customer > DictionaryOfIntegerToCustomer { get ; } = new Dictionary < int , Customer > ( ) ;
141
+ public IDictionary NonGenericDictionary { get ; } = new NonGenericDictionary ( ) ;
138
142
}
139
143
140
144
#if NET7_0_OR_GREATER
@@ -165,9 +169,9 @@ public void TestPocoObjectSucceeds()
165
169
var key1 = 100 ;
166
170
var value1 = new Customer ( ) { Name = "James" } ;
167
171
var model = new CustomerDictionary ( ) ;
168
- model . DictionaryOfStringToCustomer [ key1 ] = value1 ;
172
+ model . DictionaryOfIntegerToCustomer [ key1 ] = value1 ;
169
173
var patchDocument = new JsonPatchDocument ( ) ;
170
- patchDocument . Test ( $ "/DictionaryOfStringToCustomer /{ key1 } /Name", "James" ) ;
174
+ patchDocument . Test ( $ "/DictionaryOfIntegerToCustomer /{ key1 } /Name", "James" ) ;
171
175
172
176
// Act & Assert
173
177
patchDocument . ApplyTo ( model ) ;
@@ -180,9 +184,9 @@ public void TestPocoObjectFailsWhenTestValueIsNotEqualToObjectValue()
180
184
var key1 = 100 ;
181
185
var value1 = new Customer ( ) { Name = "James" } ;
182
186
var model = new CustomerDictionary ( ) ;
183
- model . DictionaryOfStringToCustomer [ key1 ] = value1 ;
187
+ model . DictionaryOfIntegerToCustomer [ key1 ] = value1 ;
184
188
var patchDocument = new JsonPatchDocument ( ) ;
185
- patchDocument . Test ( $ "/DictionaryOfStringToCustomer /{ key1 } /Name", "Mike" ) ;
189
+ patchDocument . Test ( $ "/DictionaryOfIntegerToCustomer /{ key1 } /Name", "Mike" ) ;
186
190
187
191
// Act
188
192
var exception = Assert . Throws < JsonPatchTestOperationException > ( ( ) => { patchDocument . ApplyTo ( model ) ; } ) ;
@@ -200,19 +204,19 @@ public void AddPocoObjectSucceeds()
200
204
var key2 = 200 ;
201
205
var value2 = new Customer ( ) { Name = "Mike" } ;
202
206
var model = new CustomerDictionary ( ) ;
203
- model . DictionaryOfStringToCustomer [ key1 ] = value1 ;
207
+ model . DictionaryOfIntegerToCustomer [ key1 ] = value1 ;
204
208
var patchDocument = new JsonPatchDocument ( ) ;
205
- patchDocument . Add ( $ "/DictionaryOfStringToCustomer /{ key2 } ", value2 ) ;
209
+ patchDocument . Add ( $ "/DictionaryOfIntegerToCustomer /{ key2 } ", value2 ) ;
206
210
207
211
// Act
208
212
patchDocument . ApplyTo ( model ) ;
209
213
210
214
// Assert
211
- Assert . Equal ( 2 , model . DictionaryOfStringToCustomer . Count ) ;
212
- var actualValue1 = model . DictionaryOfStringToCustomer [ key1 ] ;
215
+ Assert . Equal ( 2 , model . DictionaryOfIntegerToCustomer . Count ) ;
216
+ var actualValue1 = model . DictionaryOfIntegerToCustomer [ key1 ] ;
213
217
Assert . NotNull ( actualValue1 ) ;
214
218
Assert . Equal ( "James" , actualValue1 . Name ) ;
215
- var actualValue2 = model . DictionaryOfStringToCustomer [ key2 ] ;
219
+ var actualValue2 = model . DictionaryOfIntegerToCustomer [ key2 ] ;
216
220
Assert . NotNull ( actualValue2 ) ;
217
221
Assert . Equal ( "Mike" , actualValue2 . Name ) ;
218
222
}
@@ -226,17 +230,17 @@ public void AddReplacesPocoObjectSucceeds()
226
230
var key2 = 200 ;
227
231
var value2 = new Customer ( ) { Name = "Mike" } ;
228
232
var model = new CustomerDictionary ( ) ;
229
- model . DictionaryOfStringToCustomer [ key1 ] = value1 ;
230
- model . DictionaryOfStringToCustomer [ key2 ] = value2 ;
233
+ model . DictionaryOfIntegerToCustomer [ key1 ] = value1 ;
234
+ model . DictionaryOfIntegerToCustomer [ key2 ] = value2 ;
231
235
var patchDocument = new JsonPatchDocument ( ) ;
232
- patchDocument . Add ( $ "/DictionaryOfStringToCustomer /{ key1 } /Name", "James" ) ;
236
+ patchDocument . Add ( $ "/DictionaryOfIntegerToCustomer /{ key1 } /Name", "James" ) ;
233
237
234
238
// Act
235
239
patchDocument . ApplyTo ( model ) ;
236
240
237
241
// Assert
238
- Assert . Equal ( 2 , model . DictionaryOfStringToCustomer . Count ) ;
239
- var actualValue1 = model . DictionaryOfStringToCustomer [ key1 ] ;
242
+ Assert . Equal ( 2 , model . DictionaryOfIntegerToCustomer . Count ) ;
243
+ var actualValue1 = model . DictionaryOfIntegerToCustomer [ key1 ] ;
240
244
Assert . NotNull ( actualValue1 ) ;
241
245
Assert . Equal ( "James" , actualValue1 . Name ) ;
242
246
}
@@ -271,16 +275,16 @@ public void RemovePocoObjectSucceeds()
271
275
var key2 = 200 ;
272
276
var value2 = new Customer ( ) { Name = "Mike" } ;
273
277
var model = new CustomerDictionary ( ) ;
274
- model . DictionaryOfStringToCustomer [ key1 ] = value1 ;
275
- model . DictionaryOfStringToCustomer [ key2 ] = value2 ;
278
+ model . DictionaryOfIntegerToCustomer [ key1 ] = value1 ;
279
+ model . DictionaryOfIntegerToCustomer [ key2 ] = value2 ;
276
280
var patchDocument = new JsonPatchDocument ( ) ;
277
- patchDocument . Remove ( $ "/DictionaryOfStringToCustomer /{ key1 } /Name") ;
281
+ patchDocument . Remove ( $ "/DictionaryOfIntegerToCustomer /{ key1 } /Name") ;
278
282
279
283
// Act
280
284
patchDocument . ApplyTo ( model ) ;
281
285
282
286
// Assert
283
- var actualValue1 = model . DictionaryOfStringToCustomer [ key1 ] ;
287
+ var actualValue1 = model . DictionaryOfIntegerToCustomer [ key1 ] ;
284
288
Assert . Null ( actualValue1 . Name ) ;
285
289
}
286
290
@@ -293,16 +297,16 @@ public void MovePocoObjectSucceeds()
293
297
var key2 = 200 ;
294
298
var value2 = new Customer ( ) { Name = "Mike" } ;
295
299
var model = new CustomerDictionary ( ) ;
296
- model . DictionaryOfStringToCustomer [ key1 ] = value1 ;
297
- model . DictionaryOfStringToCustomer [ key2 ] = value2 ;
300
+ model . DictionaryOfIntegerToCustomer [ key1 ] = value1 ;
301
+ model . DictionaryOfIntegerToCustomer [ key2 ] = value2 ;
298
302
var patchDocument = new JsonPatchDocument ( ) ;
299
- patchDocument . Move ( $ "/DictionaryOfStringToCustomer /{ key1 } /Name", $ "/DictionaryOfStringToCustomer /{ key2 } /Name") ;
303
+ patchDocument . Move ( $ "/DictionaryOfIntegerToCustomer /{ key1 } /Name", $ "/DictionaryOfIntegerToCustomer /{ key2 } /Name") ;
300
304
301
305
// Act
302
306
patchDocument . ApplyTo ( model ) ;
303
307
304
308
// Assert
305
- var actualValue2 = model . DictionaryOfStringToCustomer [ key2 ] ;
309
+ var actualValue2 = model . DictionaryOfIntegerToCustomer [ key2 ] ;
306
310
Assert . NotNull ( actualValue2 ) ;
307
311
Assert . Equal ( "James" , actualValue2 . Name ) ;
308
312
}
@@ -316,17 +320,17 @@ public void CopyPocoObjectSucceeds()
316
320
var key2 = 200 ;
317
321
var value2 = new Customer ( ) { Name = "Mike" } ;
318
322
var model = new CustomerDictionary ( ) ;
319
- model . DictionaryOfStringToCustomer [ key1 ] = value1 ;
320
- model . DictionaryOfStringToCustomer [ key2 ] = value2 ;
323
+ model . DictionaryOfIntegerToCustomer [ key1 ] = value1 ;
324
+ model . DictionaryOfIntegerToCustomer [ key2 ] = value2 ;
321
325
var patchDocument = new JsonPatchDocument ( ) ;
322
- patchDocument . Copy ( $ "/DictionaryOfStringToCustomer /{ key1 } /Name", $ "/DictionaryOfStringToCustomer /{ key2 } /Name") ;
326
+ patchDocument . Copy ( $ "/DictionaryOfIntegerToCustomer /{ key1 } /Name", $ "/DictionaryOfIntegerToCustomer /{ key2 } /Name") ;
323
327
324
328
// Act
325
329
patchDocument . ApplyTo ( model ) ;
326
330
327
331
// Assert
328
- Assert . Equal ( 2 , model . DictionaryOfStringToCustomer . Count ) ;
329
- var actualValue2 = model . DictionaryOfStringToCustomer [ key2 ] ;
332
+ Assert . Equal ( 2 , model . DictionaryOfIntegerToCustomer . Count ) ;
333
+ var actualValue2 = model . DictionaryOfIntegerToCustomer [ key2 ] ;
330
334
Assert . NotNull ( actualValue2 ) ;
331
335
Assert . Equal ( "James" , actualValue2 . Name ) ;
332
336
}
@@ -340,17 +344,17 @@ public void ReplacePocoObjectSucceeds()
340
344
var key2 = 200 ;
341
345
var value2 = new Customer ( ) { Name = "Mike" } ;
342
346
var model = new CustomerDictionary ( ) ;
343
- model . DictionaryOfStringToCustomer [ key1 ] = value1 ;
344
- model . DictionaryOfStringToCustomer [ key2 ] = value2 ;
347
+ model . DictionaryOfIntegerToCustomer [ key1 ] = value1 ;
348
+ model . DictionaryOfIntegerToCustomer [ key2 ] = value2 ;
345
349
var patchDocument = new JsonPatchDocument ( ) ;
346
- patchDocument . Replace ( $ "/DictionaryOfStringToCustomer /{ key1 } /Name", "James" ) ;
350
+ patchDocument . Replace ( $ "/DictionaryOfIntegerToCustomer /{ key1 } /Name", "James" ) ;
347
351
348
352
// Act
349
353
patchDocument . ApplyTo ( model ) ;
350
354
351
355
// Assert
352
- Assert . Equal ( 2 , model . DictionaryOfStringToCustomer . Count ) ;
353
- var actualValue1 = model . DictionaryOfStringToCustomer [ key1 ] ;
356
+ Assert . Equal ( 2 , model . DictionaryOfIntegerToCustomer . Count ) ;
357
+ var actualValue1 = model . DictionaryOfIntegerToCustomer [ key1 ] ;
354
358
Assert . NotNull ( actualValue1 ) ;
355
359
Assert . Equal ( "James" , actualValue1 . Name ) ;
356
360
}
@@ -379,4 +383,118 @@ public void ReplacePocoObjectWithEscapingSucceeds()
379
383
Assert . Equal ( 300 , actualValue1 ) ;
380
384
Assert . Equal ( 200 , actualValue2 ) ;
381
385
}
386
+
387
+ [ Theory ]
388
+ [ InlineData ( "test" , "DictionaryOfStringToInteger" ) ]
389
+ [ InlineData ( "move" , "DictionaryOfStringToInteger" ) ]
390
+ [ InlineData ( "copy" , "DictionaryOfStringToInteger" ) ]
391
+ [ InlineData ( "test" , "NonGenericDictionary" ) ]
392
+ [ InlineData ( "move" , "NonGenericDictionary" ) ]
393
+ [ InlineData ( "copy" , "NonGenericDictionary" ) ]
394
+ public void ReadIntegerValueOfMissingKeyThrowsJsonPatchExceptionWithDefaultErrorReporter ( string op , string dictionaryPropertyName )
395
+ {
396
+ // Arrange
397
+ var model = new IntDictionary ( ) ;
398
+ var missingKey = "eight" ;
399
+ var operation = new Operation < IntDictionary > (
400
+ op ,
401
+ path : $ "/{ dictionaryPropertyName } /{ missingKey } ",
402
+ from : $ "/{ dictionaryPropertyName } /{ missingKey } ",
403
+ value : 8 ) ;
404
+
405
+ var patchDocument = new JsonPatchDocument < IntDictionary > ( ) ;
406
+ patchDocument . Operations . Add ( operation ) ;
407
+
408
+ // Act
409
+ var exception = Assert . Throws < JsonPatchException > ( ( ) => { patchDocument . ApplyTo ( model ) ; } ) ;
410
+
411
+ // Assert
412
+ Assert . Equal ( $ "The target location specified by path segment '{ missingKey } ' was not found.", exception . Message ) ;
413
+ }
414
+
415
+ [ Theory ]
416
+ [ InlineData ( "test" , "DictionaryOfStringToInteger" ) ]
417
+ [ InlineData ( "move" , "DictionaryOfStringToInteger" ) ]
418
+ [ InlineData ( "copy" , "DictionaryOfStringToInteger" ) ]
419
+ [ InlineData ( "test" , "NonGenericDictionary" ) ]
420
+ [ InlineData ( "move" , "NonGenericDictionary" ) ]
421
+ [ InlineData ( "copy" , "NonGenericDictionary" ) ]
422
+ public void ReadIntegerValueOfMissingKeyDoesNotThrowExceptionWithCustomErrorReporter ( string op , string dictionaryPropertyName )
423
+ {
424
+ // Arrange
425
+ var patchErrorLogger = new TestErrorLogger < DictionaryTest > ( ) ;
426
+ var model = new IntDictionary ( ) ;
427
+ var missingKey = "eight" ;
428
+ var operation = new Operation < IntDictionary > (
429
+ op ,
430
+ path : $ "/{ dictionaryPropertyName } /{ missingKey } ",
431
+ from : $ "/{ dictionaryPropertyName } /{ missingKey } ",
432
+ value : 8 ) ;
433
+
434
+ var patchDocument = new JsonPatchDocument < IntDictionary > ( ) ;
435
+ patchDocument . Operations . Add ( operation ) ;
436
+
437
+ // Act
438
+ patchDocument . ApplyTo ( model , patchErrorLogger . LogErrorMessage ) ;
439
+
440
+ // Assert
441
+ Assert . Equal ( $ "The target location specified by path segment '{ missingKey } ' was not found.", patchErrorLogger . ErrorMessage ) ;
442
+ }
443
+
444
+ [ Theory ]
445
+ [ InlineData ( "test" , "DictionaryOfIntegerToCustomer" ) ]
446
+ [ InlineData ( "move" , "DictionaryOfIntegerToCustomer" ) ]
447
+ [ InlineData ( "copy" , "DictionaryOfIntegerToCustomer" ) ]
448
+ [ InlineData ( "test" , "NonGenericDictionary" ) ]
449
+ [ InlineData ( "move" , "NonGenericDictionary" ) ]
450
+ [ InlineData ( "copy" , "NonGenericDictionary" ) ]
451
+ public void ReadPocoObjectValueOfMissingKeyThrowsJsonPatchExceptionWithDefaultErrorReporter ( string op , string dictionaryPropertyName )
452
+ {
453
+ // Arrange
454
+ var model = new CustomerDictionary ( ) ;
455
+ var missingKey = 8 ;
456
+ var operation = new Operation < CustomerDictionary > (
457
+ op ,
458
+ path : $ "/{ dictionaryPropertyName } /{ missingKey } /Address/City",
459
+ from : $ "/{ dictionaryPropertyName } /{ missingKey } /Address/City",
460
+ value : "Nowhere" ) ;
461
+
462
+ var patchDocument = new JsonPatchDocument < CustomerDictionary > ( ) ;
463
+ patchDocument . Operations . Add ( operation ) ;
464
+
465
+ // Act
466
+ var exception = Assert . Throws < JsonPatchException > ( ( ) => { patchDocument . ApplyTo ( model ) ; } ) ;
467
+
468
+ // Assert
469
+ Assert . Equal ( $ "The target location specified by path segment '{ missingKey } ' was not found.", exception . Message ) ;
470
+ }
471
+
472
+ [ Theory ]
473
+ [ InlineData ( "test" , "DictionaryOfIntegerToCustomer" ) ]
474
+ [ InlineData ( "move" , "DictionaryOfIntegerToCustomer" ) ]
475
+ [ InlineData ( "copy" , "DictionaryOfIntegerToCustomer" ) ]
476
+ [ InlineData ( "test" , "NonGenericDictionary" ) ]
477
+ [ InlineData ( "move" , "NonGenericDictionary" ) ]
478
+ [ InlineData ( "copy" , "NonGenericDictionary" ) ]
479
+ public void ReadPocoObjectValueOfMissingKeyDoesNotThrowExceptionWithCustomErrorReporter ( string op , string dictionaryPropertyName )
480
+ {
481
+ // Arrange
482
+ var patchErrorLogger = new TestErrorLogger < DictionaryTest > ( ) ;
483
+ var model = new CustomerDictionary ( ) ;
484
+ var missingKey = 8 ;
485
+ var operation = new Operation < CustomerDictionary > (
486
+ op ,
487
+ path : $ "/{ dictionaryPropertyName } /{ missingKey } /Address/City",
488
+ from : $ "/{ dictionaryPropertyName } /{ missingKey } /Address/City",
489
+ value : "Nowhere" ) ;
490
+
491
+ var patchDocument = new JsonPatchDocument < CustomerDictionary > ( ) ;
492
+ patchDocument . Operations . Add ( operation ) ;
493
+
494
+ // Act
495
+ patchDocument . ApplyTo ( model , patchErrorLogger . LogErrorMessage ) ;
496
+
497
+ // Assert
498
+ Assert . Equal ( $ "The target location specified by path segment '{ missingKey } ' was not found.", patchErrorLogger . ErrorMessage ) ;
499
+ }
382
500
}
0 commit comments