InlineAutoDataAttribute and xUnit.net 1.9 Generic Theories

Developer
Feb 15, 2012 at 11:12 AM

This code works:

[Theory, InlineAutoData(typeof(Order))]
public void Foo<T>(T order)
{
}

While this code throws an exception:

[Theory, InlineAutoData(typeof(Order))]
public void Foo<T>(T order, string s)
{
}

To me it looks more like a breaking change in Data Theories but I include the exception message in order to investigate further.

System.InvalidOperationException : An exception was thrown while getting data for theory OrderServiceTests.Foo:

Ploeh.AutoFixture.ObjectCreationException: AutoFixture was unable to create an instance from T, most likely because it has no public constructor. 

at Ploeh.AutoFixture.Kernel.TerminatingSpecimenBuilder.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b) 

at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()   

at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 

at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a5`1.MoveNext() 

at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context) 

at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.SpecimenContext.Resolve(Object request)

at Ploeh.AutoFixture.Kernel.SeedIgnoringRelay.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b)   

at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()   

at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()   

at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a5`1.MoveNext()   

at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b)   

at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()   

at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()   

at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a5`1.MoveNext()   

at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.SpecimenContext.Resolve(Object request)   

at Ploeh.AutoFixture.Kernel.ParameterRequestRelay.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b)   

at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()   

at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 

at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a5`1.MoveNext()   

at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b)   

at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()   

at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()   

at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a5`1.MoveNext()   

at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)   

at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)   

at Ploeh.AutoFixture.Kernel.SpecimenContext.Resolve(Object request)   

at Ploeh.AutoFixture.Xunit.AutoDataAttribute.Resolve(ParameterInfo p)   

at Ploeh.AutoFixture.Xunit.AutoDataAttribute.GetData(MethodInfo methodUnderTest, Type[] parameterTypes)   

at Ploeh.AutoFixture.Xunit.CompositeDataAttribute.<GetData>d__0.MoveNext()   

at Xunit.Extensions.TheoryAttribute.<GetData>d__7.MoveNext()   

at Xunit.Extensions.TheoryAttribute.EnumerateTestCommands(IMethodInfo method)

at Xunit.Extensions.TheoryAttribute.<>c__DisplayClass5.<EnumerateTestCommands>b__1()

at Xunit.Extensions.TheoryAttribute.LambdaTestCommand.Execute(Object testClass)

Coordinator
Feb 15, 2012 at 2:08 PM

Does Order have a default constructor?

Developer
Feb 15, 2012 at 2:29 PM

Yes, it has.

Coordinator
Feb 19, 2012 at 12:05 PM

That's pretty strange because the error message claims that it doesn't. Looks like there's a bug somewhere...

Developer
Feb 19, 2012 at 8:25 PM
Edited Feb 19, 2012 at 8:28 PM

Here is another example.

This works: 

[Theory, InlineAutoData("foo", "bar", "foo-bar")]
public void Foo<T>(T a, T b, T c)
{
}

However, the code below doesn't (both methods throw the same exception as above):

[Theory, InlineAutoData("foo", "bar")]
public void Foo<T>(T a, T b, T c)
{
}

[Theory, AutoData]
public void Foo<T>(T a, T b, T c)
{ 
}

Inside the AutoDataAttribute class, the code iterates through the parameters of the method under test. 

For each parameter it tries to create a specimen, however, the parameter is generic type so an exception is thrown because at this point there is no information on what type to create...

Coordinator
Feb 19, 2012 at 10:47 PM

Oh, you're using the new xUnit.net 1.9 support for generics?

Developer
Feb 19, 2012 at 10:53 PM

I am trying it, actually.

I think this is normal behavior.. (AutoData can't guess what the T is.)

Coordinator
Feb 19, 2012 at 11:07 PM

Yes, that sounds reasonable. Have you tried this alternative (which has been available all along)?

Developer
Feb 20, 2012 at 9:41 AM

AFAICT, this one applies to class level, though the generic theories of xUnit 1.9 apply to method level (which means, that the class itself may not be generic).

Since the behavior is normal, I think there is no action to be taken. :)