Skip to content

Commit f466d81

Browse files
committed
#2927: Misleading error message when class used in IClassFixture<> throws exception in constructor
1 parent 1911ea7 commit f466d81

4 files changed

Lines changed: 48 additions & 5 deletions

File tree

src/xunit.execution/Sdk/Frameworks/Runners/TestClassRunner.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ protected virtual object[] CreateTestClassConstructorArguments()
123123
unusedArguments.Add(Tuple.Create(idx, parameter));
124124
}
125125

126-
if (unusedArguments.Count > 0)
126+
if (unusedArguments.Count > 0 && !Aggregator.HasExceptions)
127127
Aggregator.Add(new TestClassException(FormatConstructorArgsMissingMessage(ctor, unusedArguments)));
128128

129129
return constructorArguments;

src/xunit.execution/Sdk/Frameworks/Runners/XunitTestClassRunner.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,14 @@ protected virtual void CreateClassFixture(Type fixtureType)
9797
);
9898
else
9999
{
100-
Aggregator.Run(() => ClassFixtureMappings[fixtureType] = ctor.Invoke(ctorArgs));
100+
try
101+
{
102+
ClassFixtureMappings[fixtureType] = ctor.Invoke(ctorArgs);
103+
}
104+
catch (Exception ex)
105+
{
106+
Aggregator.Add(new TestClassException(string.Format(CultureInfo.CurrentCulture, "Class fixture type '{0}' threw in its constructor", fixtureType.FullName), ex.Unwrap()));
107+
}
101108
}
102109
}
103110

src/xunit.execution/Sdk/TestClassException.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ public TestClassException(string message)
2020
: base(message)
2121
{ }
2222

23+
/// <summary>
24+
/// Initializes a new instance of the <see cref="TestClassException"/> class.
25+
/// </summary>
26+
/// <param name="message">The exception message.</param>
27+
/// <param name="innerException">The inner exception.</param>
28+
public TestClassException(string message, Exception innerException)
29+
: base(message, innerException)
30+
{ }
31+
2332
#if NETFRAMEWORK
2433
/// <inheritdoc/>
2534
protected TestClassException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)

test/test.xunit.execution/Acceptance/FixtureAcceptanceTests.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,17 @@ public void TheTest() { }
106106
}
107107

108108
[Fact]
109-
public void TestClassWithThrowingFixtureConstructorResultsInFailedTest()
109+
public void TestClassWithoutCtorWithThrowingFixtureConstructorResultsInFailedTest()
110110
{
111111
var messages = Run<ITestFailed>(typeof(ClassWithThrowingFixtureCtor));
112112

113113
var msg = Assert.Single(messages);
114-
Assert.Equal(typeof(DivideByZeroException).FullName, msg.ExceptionTypes.Single());
114+
Assert.Collection(
115+
msg.ExceptionTypes,
116+
exceptionTypeName => Assert.Equal(typeof(TestClassException).FullName, exceptionTypeName),
117+
exceptionTypeName => Assert.Equal(typeof(DivideByZeroException).FullName, exceptionTypeName)
118+
);
119+
Assert.Equal("Class fixture type 'FixtureAcceptanceTests+ThrowingCtorFixture' threw in its constructor", msg.Messages.First());
115120
}
116121

117122
class ClassWithThrowingFixtureCtor : IClassFixture<ThrowingCtorFixture>
@@ -120,6 +125,28 @@ class ClassWithThrowingFixtureCtor : IClassFixture<ThrowingCtorFixture>
120125
public void TheTest() { }
121126
}
122127

128+
[Fact]
129+
public void TestClassWithCtorWithThrowingFixtureConstructorResultsInFailedTest()
130+
{
131+
var messages = Run<ITestFailed>(typeof(ClassWithCtorAndThrowingFixtureCtor));
132+
133+
var msg = Assert.Single(messages);
134+
Assert.Collection(
135+
msg.ExceptionTypes,
136+
exceptionTypeName => Assert.Equal(typeof(TestClassException).FullName, exceptionTypeName),
137+
exceptionTypeName => Assert.Equal(typeof(DivideByZeroException).FullName, exceptionTypeName)
138+
);
139+
Assert.Equal("Class fixture type 'FixtureAcceptanceTests+ThrowingCtorFixture' threw in its constructor", msg.Messages.First());
140+
}
141+
142+
class ClassWithCtorAndThrowingFixtureCtor : IClassFixture<ThrowingCtorFixture>
143+
{
144+
public ClassWithCtorAndThrowingFixtureCtor(ThrowingCtorFixture _) { }
145+
146+
[Fact]
147+
public void TheTest() { }
148+
}
149+
123150
[Fact]
124151
public void TestClassWithThrowingFixtureDisposeResultsInFailedTest()
125152
{
@@ -186,7 +213,7 @@ public void TestClassWithOptionalParameter()
186213

187214
class ClassWithOptionalCtorArg : IClassFixture<EmptyFixtureData>
188215
{
189-
public ClassWithOptionalCtorArg(EmptyFixtureData fixture, [Optional]int x, [Optional]object y)
216+
public ClassWithOptionalCtorArg(EmptyFixtureData fixture, [Optional] int x, [Optional] object y)
190217
{
191218
Assert.NotNull(fixture);
192219
Assert.Equal(0, x);

0 commit comments

Comments
 (0)