Skip to content

Commit 6848faf

Browse files
Add async catch method (#430)
1 parent 510403c commit 6848faf

File tree

6 files changed

+154
-5
lines changed

6 files changed

+154
-5
lines changed

src/Machine.Specifications.Specs/CatchSpecs.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Threading.Tasks;
23

34
namespace Machine.Specifications.Specs
45
{
@@ -130,4 +131,49 @@ public class with_a_non_throwing_Action
130131
result.ShouldBeNull();
131132
}
132133
}
134+
135+
[Subject(typeof(Catch))]
136+
public class when_calling_catch_with_async_methods
137+
{
138+
static Exception exception;
139+
140+
[Subject(typeof(Catch))]
141+
public class with_a_non_throwing_action
142+
{
143+
static Task Test() => Task.Run(() => { });
144+
145+
Because of = async () =>
146+
exception = await Catch.ExceptionAsync(Test);
147+
148+
It should_return_null = () =>
149+
exception.ShouldBeNull();
150+
}
151+
152+
[Subject(typeof(Catch))]
153+
public class with_a_throwing_action
154+
{
155+
static Task Test() => Task.Run(() => throw new ArgumentNullException());
156+
157+
Because of = async () =>
158+
exception = await Catch.ExceptionAsync(Test);
159+
160+
It should_return_exception = () =>
161+
exception.ShouldBeOfExactType<ArgumentNullException>();
162+
}
163+
164+
[Subject(typeof(Catch))]
165+
public class calling_wrong_catch_method
166+
{
167+
static Task Test() => Task.Run(() => throw new ArgumentNullException());
168+
169+
Because of = () =>
170+
exception = Catch.Exception(() => Catch.Exception(Test));
171+
172+
It should_return_exception = () =>
173+
exception.ShouldBeOfExactType<InvalidOperationException>();
174+
175+
It should_contain_message = () =>
176+
exception.Message.ShouldEqual("You must use Catch.ExceptionAsync for async methods");
177+
}
178+
}
133179
}

src/Machine.Specifications.Specs/CompileContext.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO;
55
using System.Linq;
66
using System.Reflection;
7+
using System.Threading.Tasks;
78
using Microsoft.CodeAnalysis;
89
using Microsoft.CodeAnalysis.CSharp;
910
using Microsoft.CSharp;
@@ -44,7 +45,8 @@ public string Compile(string code)
4445
{
4546
"Machine.Specifications.dll",
4647
"Machine.Specifications.Should.dll",
47-
"netstandard.dll"
48+
"netstandard.dll",
49+
$"{typeof(ValueTask).Assembly.GetName().Name}.dll"
4850
});
4951

5052
var options = new Dictionary<string, string> {{"CompilerVersion", "v4.0"}};
@@ -53,7 +55,7 @@ public string Compile(string code)
5355
var results = provider.CompileAssemblyFromSource(parameters, code);
5456

5557
if (results.Errors.Count > 0)
56-
throw new InvalidOperationException();
58+
throw new InvalidOperationException(results.Errors[0].ErrorText);
5759
#endif
5860
return filename;
5961
}

src/Machine.Specifications.Specs/Fixtures/RandomFixture.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,39 @@ public class AsyncSpecifications
10921092
};
10931093
}
10941094
1095+
public class AsyncSpecificationsValueTask
1096+
{
1097+
public static int establish_value;
1098+
1099+
public static int because_value;
1100+
1101+
public static int async_it_value;
1102+
1103+
public static int sync_it_value;
1104+
1105+
public static int cleanup_value;
1106+
1107+
public static ValueTask<int> Test()
1108+
{
1109+
return new ValueTask<int>(10);
1110+
}
1111+
1112+
Establish context = async () =>
1113+
establish_value = await Test();
1114+
1115+
Because of = async () =>
1116+
because_value = await Test();
1117+
1118+
It should_invoke_sync = () =>
1119+
sync_it_value = Test().Result;
1120+
1121+
It should_invoke_async = async () =>
1122+
async_it_value = await Test();
1123+
1124+
Cleanup after = async () =>
1125+
cleanup_value = await Test();
1126+
}
1127+
10951128
public class AsyncSpecificationsWithExceptions
10961129
{
10971130
Because of = async () =>

src/Machine.Specifications.Specs/Runner/AsyncDelegateRunnerSpecs.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Linq;
3+
using System.Threading.Tasks;
34
using Machine.Specifications.Factories;
45
using Machine.Specifications.Runner;
56
using Machine.Specifications.Runner.Impl;
@@ -75,4 +76,39 @@ public class when_running_async_specifications_with_exceptions : RandomRunnerSpe
7576
It should_have_failures = () =>
7677
results.ShouldEachConformTo(x => !x.Passed);
7778
}
79+
80+
[Subject("Async Delegate Runner")]
81+
public class when_running_async_value_task_specifications : RandomRunnerSpecs
82+
{
83+
static Type specs;
84+
85+
Establish context = () =>
86+
{
87+
specs = GetFramework("AsyncSpecificationsValueTask");
88+
89+
specs.ToDynamic().establish_value = 0;
90+
specs.ToDynamic().because_value = 0;
91+
specs.ToDynamic().async_it_value = 0;
92+
specs.ToDynamic().sync_it_value = 0;
93+
specs.ToDynamic().cleanup_value = 0;
94+
};
95+
96+
Because of = () =>
97+
Run(specs);
98+
99+
It should_call_establish = () =>
100+
specs.ToDynamic().establish_value.ShouldEqual(10);
101+
102+
It should_call_because = () =>
103+
specs.ToDynamic().because_value.ShouldEqual(10);
104+
105+
It should_call_async_spec = () =>
106+
specs.ToDynamic().async_it_value.ShouldEqual(10);
107+
108+
It should_call_sync_spec = () =>
109+
specs.ToDynamic().sync_it_value.ShouldEqual(10);
110+
111+
It should_call_cleanup = () =>
112+
specs.ToDynamic().cleanup_value.ShouldEqual(10);
113+
}
78114
}

src/Machine.Specifications/Catch.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,61 @@
11
using System;
2+
using System.Threading.Tasks;
23

34
namespace Machine.Specifications
45
{
56
public static class Catch
67
{
78
public static Exception Exception(Action throwingAction)
89
{
9-
return Only<Exception>(throwingAction);
10+
try
11+
{
12+
throwingAction();
13+
}
14+
catch (Exception ex)
15+
{
16+
return ex;
17+
}
18+
19+
return null;
1020
}
1121

1222
public static Exception Exception<T>(Func<T> throwingFunc)
1323
{
24+
Task task;
25+
1426
try
1527
{
16-
throwingFunc();
28+
task = throwingFunc() as Task;
1729
}
1830
catch (Exception exception)
1931
{
2032
return exception;
2133
}
2234

35+
if (task != null)
36+
{
37+
throw new InvalidOperationException("You must use Catch.ExceptionAsync for async methods");
38+
}
39+
40+
return null;
41+
}
42+
43+
public static async Task<Exception> ExceptionAsync(Func<Task> throwingAction)
44+
{
45+
try
46+
{
47+
await throwingAction();
48+
}
49+
catch (Exception ex)
50+
{
51+
return ex;
52+
}
53+
2354
return null;
2455
}
2556

2657
public static TException Only<TException>(Action throwingAction)
27-
where TException : Exception
58+
where TException : Exception
2859
{
2960
try
3061
{

src/Machine.Specifications/Machine.Specifications.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515
<ItemGroup>
1616
<None Include="Resources\Machine.png" Pack="true" PackagePath="\" />
1717
</ItemGroup>
18+
1819
</Project>

0 commit comments

Comments
 (0)