Skip to content

Commit ccfcd5f

Browse files
authored
Fix async finally block bug + add unit tests for bug (and two unit tests for happy-path execution with both regular and async finally blocks) (#82)
1 parent 8081f29 commit ccfcd5f

File tree

3 files changed

+123
-1
lines changed

3 files changed

+123
-1
lines changed

IntelliTect.TestTools.TestFramework.Tests/TestCaseTests/FinallyExecutionTests.cs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,22 @@ namespace IntelliTect.TestTools.TestFramework.Tests.TestCaseTests
88
{
99
public class FinallyExecutionTests
1010
{
11+
[Fact]
12+
public async Task NoExceptionsWhenAllBlocksAndFinallyBlocksPass()
13+
{
14+
// Arrange
15+
TestCase tc = new TestBuilder()
16+
.AddDependencyInstance(true)
17+
.AddTestBlock<ExampleTestBlockWithBoolReturn>()
18+
.AddFinallyBlock<ExampleFinallyBlock>(true)
19+
.Build();
20+
21+
// Act
22+
await tc.ExecuteAsync();
23+
24+
// Assert
25+
Assert.True(tc.Passed, "Test case did not get marked as Passed when we expected it.");
26+
}
1127

1228
[Fact]
1329
public async Task FinallyBlockThrowsExpectedExceptionWhenNotOverridingDefaultFinallyBehavior()
@@ -88,5 +104,102 @@ public async Task OnlyTestBlockThrowsExpectedExceptionWhenOverridingDefaultFinal
88104
// Assert
89105
Assert.False(tc.Passed, "Test case did not get marked as Failed when we expected it.");
90106
}
107+
108+
[Fact]
109+
public async Task NoExceptionsWhenAllBlocksAndAsyncFinallyBlocksPass()
110+
{
111+
// Arrange
112+
TestCase tc = new TestBuilder()
113+
.AddDependencyInstance(true)
114+
.AddTestBlock<ExampleTestBlockWithBoolReturn>()
115+
.AddAsyncFinallyBlock<ExampleAsyncFinallyBlock>(true)
116+
.Build();
117+
118+
// Act
119+
await tc.ExecuteAsync();
120+
121+
// Assert
122+
Assert.True(tc.Passed, "Test case did not get marked as Passed when we expected it.");
123+
}
124+
125+
[Fact]
126+
public async Task AsyncFinallyBlockThrowsExpectedExceptionWhenNotOverridingDefaultFinallyBehavior()
127+
{
128+
// Arrange
129+
TestCase tc = new TestBuilder()
130+
.AddDependencyInstance(true)
131+
.AddTestBlock<ExampleTestBlockWithBoolReturn>()
132+
.AddAsyncFinallyBlock<ExampleAsyncFinallyBlock>()
133+
.Build();
134+
135+
// Act
136+
var ex = await Assert.ThrowsAsync<AggregateException>(() => tc.ExecuteAsync());
137+
138+
// Assert
139+
Assert.NotNull(ex.InnerExceptions);
140+
Assert.Single(ex.InnerExceptions);
141+
Assert.Contains("Test case succeeded",
142+
ex.Message,
143+
StringComparison.InvariantCultureIgnoreCase);
144+
Assert.True(tc.Passed, "Test case did not get marked as Passed when we expected it.");
145+
}
146+
147+
[Fact]
148+
public async Task TestBlockAndAsyncFinallyBlockThrowsExpectedExceptionWhenNotOverridingDefaultFinallyBehavior()
149+
{
150+
// Arrange
151+
TestCase tc = new TestBuilder()
152+
.AddDependencyInstance(false)
153+
.AddTestBlock<ExampleTestBlockWithBoolReturn>()
154+
.AddAsyncFinallyBlock<ExampleAsyncFinallyBlock>()
155+
.Build();
156+
157+
// Act
158+
var ex = await Assert.ThrowsAsync<AggregateException>(() => tc.ExecuteAsync());
159+
160+
// Assert
161+
Assert.NotNull(ex.InnerExceptions);
162+
Assert.Equal(2, ex.InnerExceptions.Count);
163+
Assert.Contains("Test case failed and finally blocks failed",
164+
ex.Message,
165+
StringComparison.InvariantCultureIgnoreCase);
166+
Assert.False(tc.Passed, "Test case did not get marked as Failed when we expected it.");
167+
}
168+
169+
[Fact]
170+
public async Task AsyncFinallyBlockDoesNotThrowExceptionWhenOverridingDefaultFinallyBehavior()
171+
{
172+
// Arrange
173+
TestCase tc = new TestBuilder()
174+
.AddDependencyInstance(true)
175+
.AddTestBlock<ExampleTestBlockWithBoolReturn>()
176+
.AddAsyncFinallyBlock<ExampleAsyncFinallyBlock>()
177+
.Build();
178+
tc.ThrowOnFinallyBlockException = false;
179+
180+
// Act
181+
await tc.ExecuteAsync();
182+
183+
// Assert
184+
Assert.True(tc.Passed, "Test case did not get marked as Passed when we expected it.");
185+
}
186+
187+
[Fact]
188+
public async Task OnlyTestBlockThrowsExpectedExceptionWhenOverridingDefaultFinallyBehaviorWithAsyncFinallyBlock()
189+
{
190+
// Arrange
191+
TestCase tc = new TestBuilder()
192+
.AddDependencyInstance(false)
193+
.AddTestBlock<ExampleTestBlockWithBoolReturn>()
194+
.AddAsyncFinallyBlock<ExampleAsyncFinallyBlock>()
195+
.Build();
196+
tc.ThrowOnFinallyBlockException = false;
197+
198+
// Act
199+
await Assert.ThrowsAsync<TestCaseException>(() => tc.ExecuteAsync());
200+
201+
// Assert
202+
Assert.False(tc.Passed, "Test case did not get marked as Failed when we expected it.");
203+
}
91204
}
92205
}

IntelliTect.TestTools.TestFramework.Tests/TestData/Dependencies/SimulatorClasses.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,15 @@ public void Execute(bool result)
110110
}
111111
}
112112

113+
public class ExampleAsyncFinallyBlock : TestBlock
114+
{
115+
public async Task Execute(bool result)
116+
{
117+
await Task.Delay(1);
118+
Assert.True(result, "This is an expected failure.");
119+
}
120+
}
121+
113122
public class ExampleAsyncBlockWithReturn : TestBlock
114123
{
115124
public async Task<bool> Execute()

IntelliTect.TestTools.TestFramework/TestBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public TestBuilder AddAsyncFinallyBlock<T>(params object[] testBlockArgs) where
104104
Block fb = CreateBlock<T>(testBlockArgs);
105105
fb.IsFinallyBlock = true;
106106
fb.IsAsync = true;
107-
TestBlocks.Add(fb);
107+
FinallyBlocks.Add(fb);
108108
return this;
109109
}
110110

0 commit comments

Comments
 (0)