Skip to content

Commit 25ce858

Browse files
authored
Add flag for throwing on unhandled exceptions (graphql-dotnet#776)
Fixes graphql-dotnet#607
1 parent ab81a5d commit 25ce858

13 files changed

+82
-28
lines changed

src/GraphQL.Tests/Bugs/Bug68NonNullEnumGraphTypeTests.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,6 @@ public class Bug68NonNullEnumGraphTypeTests
1313
{
1414
private readonly IDocumentExecuter _executer = new DocumentExecuter();
1515

16-
ExecutionResult ExecuteQuery(ISchema schema, string query)
17-
{
18-
return _executer.ExecuteAsync(_ =>
19-
{
20-
_.Schema = schema;
21-
_.Query = query;
22-
}).GetAwaiter().GetResult();
23-
}
24-
2516
[Fact]
2617
public void only_nullable_is_happy()
2718
{
@@ -40,7 +31,16 @@ public void both_is_happy()
4031
VerifyIntrospection(new NullableSchema(true, true));
4132
}
4233

43-
public void VerifyIntrospection(ISchema schema)
34+
private ExecutionResult ExecuteQuery(ISchema schema, string query)
35+
{
36+
return _executer.ExecuteAsync(_ =>
37+
{
38+
_.Schema = schema;
39+
_.Query = query;
40+
}).GetAwaiter().GetResult();
41+
}
42+
43+
private void VerifyIntrospection(ISchema schema)
4444
{
4545
var result = ExecuteQuery(schema, SchemaIntrospection.IntrospectionQuery);
4646
result.ShouldNotBeNull();

src/GraphQL.Tests/Bugs/NullableInputListTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace GraphQL.Tests.Bugs
88
public class NullableInputListTests : QueryTestBase<TestSchema>
99
{
1010
[Fact]
11-
public async void Can_Accept_Null_List_From_Literal()
11+
public void Can_Accept_Null_List_From_Literal()
1212
{
1313
var query = @"
1414
query _ {
@@ -22,7 +22,7 @@ query _ {
2222
}
2323

2424
[Fact]
25-
public async void Can_Accept_Null_List_From_Input()
25+
public void Can_Accept_Null_List_From_Input()
2626
{
2727
var query = @"
2828
query _($inputs:[TestInput]) {

src/GraphQL.Tests/Errors/ErrorCodeTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,23 @@ public TestQuery()
6868
);
6969
FieldAsync<StringGraphType>(
7070
"firstAsync",
71-
resolve: async _ => throw new FirstException("Exception from asynchronous resolver")
71+
resolve: _ => { throw new FirstException("Exception from asynchronous resolver"); }
7272
);
7373
Field<StringGraphType>(
7474
"secondSync",
7575
resolve: _ => throw new SecondTestException("Exception from synchronous resolver")
7676
);
7777
FieldAsync<StringGraphType>(
7878
"secondAsync",
79-
resolve: async _ => throw new SecondTestException("Exception from asynchronous resolver")
79+
resolve: _ => { throw new SecondTestException("Exception from asynchronous resolver"); }
8080
);
8181
Field<StringGraphType>(
8282
"uncodedSync",
8383
resolve: _ => throw new Exception("Exception from synchronous resolver")
8484
);
8585
FieldAsync<StringGraphType>(
8686
"uncodedAsync",
87-
resolve: async _ => throw new Exception("Exception from asynchronous resolver")
87+
resolve: _ => { throw new Exception("Exception from asynchronous resolver"); }
8888
);
8989
}
9090
}

src/GraphQL.Tests/Errors/ErrorExtensionsTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,23 @@ public TestQuery()
6464
);
6565
FieldAsync<StringGraphType>(
6666
"firstAsync",
67-
resolve: async _ => throw new FirstException("Exception from asynchronous resolver")
67+
resolve: _ => { throw new FirstException("Exception from asynchronous resolver"); }
6868
);
6969
Field<StringGraphType>(
7070
"secondSync",
7171
resolve: _ => throw new SecondTestException("Exception from synchronous resolver")
7272
);
7373
FieldAsync<StringGraphType>(
7474
"secondAsync",
75-
resolve: async _ => throw new SecondTestException("Exception from asynchronous resolver")
75+
resolve: _ => { throw new SecondTestException("Exception from asynchronous resolver"); }
7676
);
7777
Field<StringGraphType>(
7878
"uncodedSync",
7979
resolve: _ => throw new Exception("Exception from synchronous resolver")
8080
);
8181
FieldAsync<StringGraphType>(
8282
"uncodedAsync",
83-
resolve: async _ => throw new Exception("Exception from asynchronous resolver")
83+
resolve: _ => { throw new Exception("Exception from asynchronous resolver"); }
8484
);
8585
}
8686
}

src/GraphQL.Tests/Errors/ErrorLocationTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public TestQuery()
107107

108108
FieldAsync<StringGraphType>(
109109
"testasync",
110-
resolve: async _ => throw new Exception("wat"));
110+
resolve: _ => { throw new Exception("wat"); });
111111

112112
Field<TestSubObject>()
113113
.Name("testSub")
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using GraphQL.Tests.Utilities;
3+
using Shouldly;
4+
using Xunit;
5+
6+
namespace GraphQL.Tests.Errors
7+
{
8+
public class UnhandledExceptionTests : SchemaBuilderTestBase
9+
{
10+
[Fact]
11+
public void rethrows_unhandled_exception()
12+
{
13+
var def = @"
14+
type Query {
15+
hello: Int
16+
}
17+
";
18+
19+
Builder.Types.Include<Query>();
20+
21+
Should.Throw<AggregateException>(() =>
22+
{
23+
AssertQuery(_ =>
24+
{
25+
_.Query = "{ hello }";
26+
_.Definitions = def;
27+
_.ThrowOnUnhandledException = true;
28+
});
29+
});
30+
}
31+
32+
public class Query
33+
{
34+
public int Hello()
35+
{
36+
throw new Exception("arrgh");
37+
}
38+
}
39+
}
40+
}

src/GraphQL.Tests/Types/SchemaTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public void registers_only_root_types()
107107
DoesNotContainTypeNames(schema, "ASchemaType!");
108108
}
109109

110-
public void ContainsTypeNames(ISchema schema, params string[] typeNames)
110+
private void ContainsTypeNames(ISchema schema, params string[] typeNames)
111111
{
112112
typeNames.Apply(typeName =>
113113
{
@@ -116,7 +116,7 @@ public void ContainsTypeNames(ISchema schema, params string[] typeNames)
116116
});
117117
}
118118

119-
public void DoesNotContainTypeNames(Schema schema, params string[] typeNames)
119+
private void DoesNotContainTypeNames(Schema schema, params string[] typeNames)
120120
{
121121
typeNames.Apply(typeName =>
122122
{

src/GraphQL.Tests/Utilities/SchemaBuilderTestBase.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public ExecutionResult AssertQuery(Action<ExecuteConfig> configure)
3434
_.Schema = schema;
3535
_.Query = config.Query;
3636
_.Inputs = config.Variables.ToInputs();
37+
_.Root = config.Root;
38+
_.ThrowOnUnhandledException = config.ThrowOnUnhandledException;
3739
}, queryResult);
3840
}
3941

@@ -75,5 +77,7 @@ public class ExecuteConfig
7577
public string Query { get; set; }
7678
public string Variables { get; set; }
7779
public string ExpectedResult { get; set; }
80+
public object Root { get; set; }
81+
public bool ThrowOnUnhandledException { get; set; }
7882
}
7983
}

src/GraphQL.Tests/Validation/KnownDirectivesTests.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ mutation Bar @onQuery {
125125
});
126126
}
127127

128-
// this is not yet supported
129-
//[Fact]
128+
[Fact]
130129
public void within_schema_language_well_placed_directives()
131130
{
132131
ShouldPassRule(@"
@@ -156,8 +155,7 @@ schema @onSchema {
156155
");
157156
}
158157

159-
// this is not yet supported
160-
//[Fact]
158+
[Fact(Skip = "This is not yet supported")]
161159
public void within_schema_language_with_misplaced_directives()
162160
{
163161
ShouldFailRule(_ =>

src/GraphQL/Execution/DocumentExecuter.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ await listener.AfterValidationAsync(
185185
options.UserContext,
186186
options.CancellationToken,
187187
metrics,
188-
options.Listeners);
188+
options.Listeners,
189+
options.ThrowOnUnhandledException);
189190

190191
if (context.Errors.Any())
191192
{
@@ -233,6 +234,9 @@ await listener.AfterExecutionAsync(context.UserContext, context.CancellationToke
233234
}
234235
catch (Exception ex)
235236
{
237+
if (options.ThrowOnUnhandledException)
238+
throw;
239+
236240
result = new ExecutionResult
237241
{
238242
Errors = new ExecutionErrors
@@ -251,7 +255,7 @@ await listener.AfterExecutionAsync(context.UserContext, context.CancellationToke
251255
return result;
252256
}
253257

254-
public ExecutionContext BuildExecutionContext(
258+
private ExecutionContext BuildExecutionContext(
255259
ISchema schema,
256260
object root,
257261
Document document,
@@ -260,7 +264,8 @@ public ExecutionContext BuildExecutionContext(
260264
object userContext,
261265
CancellationToken cancellationToken,
262266
Metrics metrics,
263-
IEnumerable<IDocumentExecutionListener> listeners)
267+
IEnumerable<IDocumentExecutionListener> listeners,
268+
bool throwOnUnhandledException)
264269
{
265270
var context = new ExecutionContext();
266271
context.Document = document;
@@ -275,6 +280,7 @@ public ExecutionContext BuildExecutionContext(
275280

276281
context.Metrics = metrics;
277282
context.Listeners = listeners;
283+
context.ThrowOnUnhandledException = throwOnUnhandledException;
278284

279285
return context;
280286
}

src/GraphQL/Execution/ExecutionContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,7 @@ public ExecutionContext()
3636
public Metrics Metrics { get; set; }
3737

3838
public IEnumerable<IDocumentExecutionListener> Listeners { get; set; } = Enumerable.Empty<IDocumentExecutionListener>();
39+
40+
public bool ThrowOnUnhandledException { get; set; }
3941
}
4042
}

src/GraphQL/Execution/ExecutionOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@ public class ExecutionOptions
3636
//Note disabling will increase performance. When true all nodes will have the middleware injected for resolving fields.
3737
public bool SetFieldMiddleware { get; set; } = true;
3838

39+
public bool ThrowOnUnhandledException { get; set; } = false;
3940
}
4041
}

src/GraphQL/Execution/ExecutionStrategy.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ protected virtual async Task<ExecutionNode> ExecuteNodeAsync(ExecutionContext co
220220
}
221221
catch (Exception ex)
222222
{
223+
if (context.ThrowOnUnhandledException)
224+
throw;
225+
223226
var error = new ExecutionError($"Error trying to resolve {node.Name}.", ex);
224227
error.AddLocation(node.Field, context.Document);
225228
error.Path = node.Path;

0 commit comments

Comments
 (0)