Skip to content

Commit cef968d

Browse files
committed
Add assert for code that throws exceptions
1 parent 5d8a807 commit cef968d

File tree

6 files changed

+145
-17
lines changed

6 files changed

+145
-17
lines changed

CHANGELOG.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22

33

44
## v0.5.0
5-
* Bugfix some datetime compare output
6-
* Add string match with `*`
5+
* Bugfix some datetime compare output.
6+
* Add support for partial string match with `*`.
7+
* Add support for asserting code that throws exceptions.
78

89
## v0.1.0
9-
* Handling uninitialized `ImmutableArray<>`
10-
* Empty objects returns empty results
11-
* Support data projection - fields can change value or be filtered away
10+
* Handling uninitialized `ImmutableArray<>`.
11+
* Empty objects returns empty results.
12+
* Add support for data projection - fields can change value or be filtered away.
1213

1314
## v0.0.3
1415
* One line printing of empty classes.
15-
* Change how configuration is passed onto `Is()`
16+
* Change how configuration is passed onto `Is()`.
1617
* Improved error messages.
1718

1819
## v0.0.2
@@ -25,4 +26,4 @@ initial test release.
2526

2627
Have fun!
2728

28-
Kasper B. Graversen
29+
Kasper B. Graversen

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,10 @@ We achieve these goals by using a novel new way of specifying asserts. Expected
9292
# 1. Getting started
9393

9494
1. Install the nuget package `ReassureTest` from nuget.org (`dotnet add package ReassureTest`)
95-
2. Use the `Is()` method in your tests (`Calculator.Add(2,3).Is("5")`)
96-
3. Done
95+
2. Write your asserts using ReassureTest
96+
* e.g. `calculator.Add(2, 3).Is("5");`
97+
* or `Reassure.Catch(() => illegalOrder.Handle()).Is(@"{ Message=&#96;Illegal number of widgets!&#96;}");`
98+
3. Done...
9799

98100

99101

@@ -387,7 +389,7 @@ e.g. the string `"some text"` is matched by all of the following: `*`, `some *`,
387389

388390

389391
### Exceptions
390-
* Exceptions are transformed into a simple form, a class containing `Message`, `Data` and `Type`.
392+
* Exceptions are transformed into a simple form, a class containing `Message` and `Type`. A `Data` field is added only when it contains elements.
391393

392394
```csharp
393395
var ex = new Exception("message") { Data = {{"a", "b"}} };

ReassureTest.Net.Tests/ThrowsTests.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using NUnit.Framework;
3+
4+
namespace ReassureTest.Tests
5+
{
6+
class ThrowsTests
7+
{
8+
[Test]
9+
public void Inline_action()
10+
{
11+
Reassure.Catch(() => throw new Exception("eee")).Is(@"{
12+
Message = `eee`
13+
Type = `System.Exception`
14+
}");
15+
16+
Reassure.With(Reassure.DefaultConfiguration).Catch(() => throw new Exception("eee")).Is(@"{
17+
Message = `eee`
18+
Type = `System.Exception`
19+
}");
20+
21+
Reassure.With(Reassure.DefaultConfiguration).Catch(() =>
22+
{
23+
var exception = new Exception("eee");
24+
exception.Data.Add("a","b");
25+
throw exception;
26+
}).Is(@"{
27+
Message = `eee`
28+
Data = [ { Key = `a` Value = `b` } ]
29+
Type = `System.Exception`
30+
}");
31+
}
32+
33+
[Test]
34+
public void Inline_func()
35+
{
36+
Reassure.Catch(() => ((string)null).Length).Is(@"{
37+
Message = `Object reference not set to an instance of an object.`
38+
Type = `System.NullReferenceException`
39+
}");
40+
41+
Reassure.With(Reassure.DefaultConfiguration).Catch(() => ((string)null).Length).Is(@"{
42+
Message = `Object reference not set to an instance of an object.`
43+
Type = `System.NullReferenceException`
44+
}");
45+
}
46+
}
47+
}

ReassureTest.Net/Reassure.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,43 @@ namespace ReassureTest
1010
{
1111
public static class Reassure
1212
{
13+
/// <summary>
14+
/// Run code and catch the exception
15+
/// </summary>
16+
public static Exception Catch(Action actual)
17+
{
18+
try
19+
{
20+
actual();
21+
}
22+
catch (Exception e)
23+
{
24+
return e;
25+
}
26+
27+
throw new AssertException($"Expected: an exception to be thrown\r\nBut no exception was throws");
28+
}
29+
30+
/// <summary>
31+
/// Run code and catch the exception
32+
/// </summary>
33+
public static Exception Catch<T>(Func<T> actual)
34+
{
35+
try
36+
{
37+
actual();
38+
}
39+
catch (Exception e)
40+
{
41+
return e;
42+
}
43+
44+
throw new AssertException($"Expected: an exception to be thrown\r\nBut no exception was throws");
45+
}
46+
47+
/// <summary>
48+
/// Assert 'actual' obeys the specification using the default configuration
49+
/// </summary>
1350
public static string Is(this object actual, string expected) => Is(actual, expected, DefaultConfiguration.DeepClone());
1451

1552
internal static string Is(this object actual, string expected, Configuration cfg)
@@ -49,8 +86,19 @@ internal static string Is(this object actual, string expected, Configuration cfg
4986
return graph;
5087
}
5188

89+
/// <summary>
90+
/// inject a configuration into a throws
91+
/// </summary>
92+
public static ReassureRunContext With(Configuration configuration) => new ReassureRunContext(configuration);
93+
94+
/// <summary>
95+
/// inject a configuration
96+
/// </summary>
5297
public static ReassureRunContext With(this object actual, Configuration configuration) => new ReassureRunContext(actual, configuration);
5398

99+
/// <summary>
100+
/// Alter this to change the general behaviour of ReassureTest
101+
/// </summary>
54102
public static Configuration DefaultConfiguration = new Configuration(
55103
new Configuration.OutputtingCfg(
56104
indention: " ",
Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,41 @@
1-
namespace ReassureTest
1+
using System;
2+
3+
namespace ReassureTest
24
{
35
public class ReassureRunContext
46
{
57
private readonly object actual;
8+
private Action alternativeActual;
9+
610
private readonly Configuration configuration;
711

8-
public ReassureRunContext(object actual, Configuration configuration)
12+
public ReassureRunContext(Configuration configuration)
913
{
10-
this.actual = actual;
1114
this.configuration = configuration.DeepClone();
1215
}
1316

14-
public string Is(string expected) => actual.Is(expected, configuration);
17+
public ReassureRunContext(object actual, Configuration configuration) : this(configuration)
18+
{
19+
this.actual = actual;
20+
}
21+
22+
public string Is(string expected)
23+
{
24+
var target = actual ?? Reassure.Catch(alternativeActual);
25+
26+
return target.Is(expected, configuration);
27+
}
28+
29+
public ReassureRunContext Catch(Action actual)
30+
{
31+
alternativeActual = actual;
32+
return this;
33+
}
34+
35+
public ReassureRunContext Catch<T>(Func<T> actual)
36+
{
37+
alternativeActual = () => actual();
38+
return this;
39+
}
1540
}
1641
}

ReassureTest.Net/ReusableProjections.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,16 @@ public static class ReusableProjections
99
{
1010
public static Flow SimplifyExceptions(object parent, object field, PropertyInfo pi)
1111
{
12-
if (field is Exception ex)
13-
return Flow.Use(new SimplifiedException(ex));
12+
if (parent is SimplifiedException
13+
&& pi.Name == "Data"
14+
&& field is IDictionary d
15+
&& d.Keys.Count == 0)
16+
{
17+
return Flow.Skip;
18+
}
1419
return Flow.Use(field);
1520
}
16-
21+
1722
public static Flow FixDefaultImmutableArrayCanNotBeTraversed(object parent, object field, PropertyInfo pi)
1823
{
1924
var type = field.GetType().ToString();

0 commit comments

Comments
 (0)