Skip to content

Commit f9f064a

Browse files
author
Svetlozar Stoykov
committed
Add extensive tests for AppendErrors method in OperationResult classes
1 parent 545967b commit f9f064a

1 file changed

Lines changed: 224 additions & 0 deletions

File tree

tests/OneBitSoftware.Utilities.OperationResultTests/OperationResultAppendErrorsTests.cs

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,4 +251,228 @@ public void AppendErrors_WithNullSource_On_GenericTarget_Returns_Same_Instance_A
251251
Assert.Same(target, returned);
252252
Assert.Equal(beforeCount, target.Errors.Count);
253253
}
254+
255+
[Fact]
256+
public void AppendErrors_PreservesResultObject_WhenMergingErrors()
257+
{
258+
// Arrange
259+
var originalResult = new { Id = 42, Name = "Test" };
260+
var target = new OperationResult<object>(originalResult);
261+
262+
var source = new OperationResult();
263+
source.AppendError("Source error", 500);
264+
265+
// Act
266+
var returned = target.AppendErrors(source);
267+
268+
// Assert
269+
Assert.Same(target, returned);
270+
Assert.Same(originalResult, target.ResultObject);
271+
Assert.Single(target.Errors);
272+
Assert.True(target.Fail);
273+
}
274+
275+
[Fact]
276+
public void AppendErrors_MaintainsFluentChaining_WithGenericType()
277+
{
278+
// Arrange
279+
var source1 = new OperationResult();
280+
source1.AppendError("E1", 1);
281+
282+
var source2 = new OperationResult<int>();
283+
source2.AppendError("E2", 2);
284+
285+
var target = new OperationResult<string>();
286+
287+
// Act - Chain multiple AppendErrors calls
288+
var returned = target
289+
.AppendErrors(source1)
290+
.AppendErrors(source2)
291+
.AppendError("E3", 3);
292+
293+
// Assert
294+
Assert.Same(target, returned);
295+
Assert.IsType<OperationResult<string>>(returned);
296+
Assert.Equal(3, target.Errors.Count);
297+
}
298+
299+
[Fact]
300+
public void AppendErrors_PreservesInitialException_FromSource()
301+
{
302+
// Arrange
303+
var sourceException = new InvalidOperationException("Source exception");
304+
var source = new OperationResult();
305+
source.AppendException(sourceException, 999);
306+
307+
var target = new OperationResult<double>();
308+
309+
// Act
310+
target.AppendErrors(source);
311+
312+
// Assert
313+
Assert.Null(target.InitialException); // Target doesn't inherit source's InitialException
314+
Assert.Single(target.Errors);
315+
Assert.Contains(sourceException.ToString(), target.Errors[0].Message);
316+
}
317+
318+
[Fact]
319+
public void AppendErrors_HandlesSourceWithMultipleErrorTypes()
320+
{
321+
// Arrange
322+
var source = new OperationResult<List<string>>();
323+
source.AppendError("Standard error", 100);
324+
source.AppendException(new ArgumentNullException("param"), 200);
325+
source.AppendError("Another error", 300, LogLevel.Critical, "Critical details");
326+
327+
var target = new OperationResult<int>();
328+
329+
// Act
330+
target.AppendErrors(source);
331+
332+
// Assert
333+
Assert.Equal(3, target.Errors.Count);
334+
Assert.NotNull(target.Errors.Single(e => e.Code == 100));
335+
Assert.NotNull(target.Errors.Single(e => e.Code == 200));
336+
Assert.NotNull(target.Errors.Single(e => e is { Code: 300, Details: "Critical details" }));
337+
}
338+
339+
[Fact]
340+
public void AppendErrors_MergesSuccessMessages_AreNotTransferred()
341+
{
342+
// Arrange
343+
var source = new OperationResult();
344+
source.AddSuccessMessage("Success from source");
345+
source.AppendError("But has error", 1);
346+
347+
var target = new OperationResult<string>();
348+
target.AddSuccessMessage("Success from target");
349+
350+
// Act
351+
target.AppendErrors(source);
352+
353+
// Assert - SuccessMessages are not merged in AppendErrors
354+
Assert.Single(target.SuccessMessages);
355+
Assert.Contains("Success from target", target.SuccessMessages);
356+
}
357+
358+
[Fact]
359+
public void AppendErrors_EmptySource_DoesNotAffectTarget()
360+
{
361+
// Arrange
362+
var source = new OperationResult(); // No errors
363+
var target = new OperationResult<string>();
364+
target.AppendError("Target error", 1);
365+
366+
// Act
367+
var returned = target.AppendErrors(source);
368+
369+
// Assert
370+
Assert.Same(target, returned);
371+
Assert.Single(target.Errors);
372+
Assert.True(target.Fail);
373+
}
374+
375+
[Fact]
376+
public void AppendErrors_EmptyTarget_AcceptsSourceErrors()
377+
{
378+
// Arrange
379+
var source = new OperationResult();
380+
source.AppendError("Source error", 100);
381+
382+
var target = new OperationResult<string>();
383+
384+
// Act
385+
target.AppendErrors(source);
386+
387+
// Assert
388+
Assert.True(target.Fail);
389+
Assert.Single(target.Errors);
390+
Assert.Equal("Source error", target.Errors[0].Message);
391+
}
392+
393+
[Fact]
394+
public void AppendErrors_WithDifferentGenericTypes_MaintainsTargetType()
395+
{
396+
// Arrange
397+
var sourceInt = new OperationResult<int> { ResultObject = 42 };
398+
sourceInt.AppendError("Int error", 1);
399+
400+
var targetString = new OperationResult<string> { ResultObject = "test" };
401+
402+
// Act
403+
var returned = targetString.AppendErrors(sourceInt);
404+
405+
// Assert
406+
Assert.IsType<OperationResult<string>>(returned);
407+
Assert.Equal("test", targetString.ResultObject);
408+
Assert.Single(targetString.Errors);
409+
}
410+
411+
[Fact]
412+
public void AppendErrors_ChainedCalls_AccumulatesAllErrors()
413+
{
414+
// Arrange
415+
var s1 = new OperationResult();
416+
s1.AppendError("E1", 1);
417+
418+
var s2 = new OperationResult<int>();
419+
s2.AppendError("E2", 2);
420+
421+
var s3 = new OperationResult();
422+
s3.AppendError("E3", 3);
423+
424+
var target = new OperationResult<string>();
425+
426+
// Act
427+
target.AppendErrors(s1).AppendErrors(s2).AppendErrors(s3);
428+
429+
// Assert
430+
Assert.Equal(3, target.Errors.Count);
431+
Assert.Contains(target.Errors, e => e.Code == 1);
432+
Assert.Contains(target.Errors, e => e.Code == 2);
433+
Assert.Contains(target.Errors, e => e.Code == 3);
434+
}
435+
436+
[Fact]
437+
public void AppendErrors_WithComplexGenericType_PreservesTypeIntegrity()
438+
{
439+
// Arrange
440+
var complexObject = new Dictionary<string, List<int>>
441+
{
442+
["key1"] = [1, 2, 3]
443+
};
444+
445+
var target = new OperationResult<Dictionary<string, List<int>>>(complexObject);
446+
var source = new OperationResult();
447+
source.AppendError("Complex type error", 999);
448+
449+
// Act
450+
var returned = target.AppendErrors(source);
451+
452+
// Assert
453+
Assert.Same(complexObject, target.ResultObject);
454+
Assert.IsType<OperationResult<Dictionary<string, List<int>>>>(returned);
455+
Assert.Single(target.Errors);
456+
}
457+
458+
[Fact]
459+
public void AppendErrors_ReturnsCorrectType_AfterMultipleOperations()
460+
{
461+
// Arrange
462+
var target = new OperationResult<int> { ResultObject = 100 };
463+
var source1 = new OperationResult();
464+
source1.AppendError("E1", 1);
465+
466+
// Act
467+
var step1 = target.AppendErrors(source1);
468+
var step2 = step1.AppendError("E2", 2);
469+
var step3 = step2.AppendException(new Exception("E3"), 3);
470+
471+
// Assert
472+
Assert.IsType<OperationResult<int>>(step1);
473+
Assert.IsType<OperationResult<int>>(step2);
474+
Assert.IsType<OperationResult<int>>(step3);
475+
Assert.Same(target, step3);
476+
Assert.Equal(3, target.Errors.Count);
477+
}
254478
}

0 commit comments

Comments
 (0)