Question

I have a struct e.g.:

public struct Foo
{
    public int Bar;
    public string Baz;
}

and would like to create it in my unit tests using autofixture. I tried using the following:

IFixture fixture = new Fixture();
var f = fixture.CreateAnonymous<Foo>();

But this throws an AutoFixture was unable to create an instance error. Is it possible to auto create a struct with autofixture? How could this be done? Please note, that I am working on legacy code and thus need to deal with structs. :)

EDIT :

Changed

IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());

To

IFixture fixture = new Fixture();

Since it wasn't relevant for the question.

Was it helpful?

Solution

This is essentially an artefact of how the C# compiler treats value types. While the documentation seems to indicate otherwise, from the perspective of Reflection, the Foo struct has no public constructors.

E.g. if you execute this code:

var ctors = typeof(Foo).GetConstructors();

the result is an empty array.

However, this code compiles:

var f = new Foo();

so you could argue that AutoFixture should be able to create an instance of Foo.

However, in the end, mutable structs are evil and should be avoided at all cost. A better option is to change the Foo implementation to this:

public struct Foo
{
    public Foo(int bar, string baz)
    {
        this.Bar = bar;
        this.Baz = baz;
    }

    public readonly int Bar;
    public readonly string Baz;
}

If you do this, not only do you now have a (more) correct value type, but AutoFixture is also able to create an instance without further modification.

Thus, this is a pretty good example of the GOOS paradigm that you should listen to your tests. If they present friction, it might be feedback about your production code. In this case, this is exactly feedback that you're about to shoot yourself in the foot because the value type implementation is flawed.

P.S. Even if you 'fix' the Foo struct like outlined above, what's the point of making it a struct instead of a class? It still contains a string (reference types) field, so even though the struct itself is going to live on the stack, the string field is still going to point to data in the heap.


I've added this issue as a possible new feature for AutoFixture.

OTHER TIPS

Taking a cue from this blog post, I created a class that implemented the ISpecimenBuilder

class FooBuilder : ISpecimenBuilder
{
  public object Create(object request, ISpecimenContext context)
  {
    var sr = request as SeededRequest;
    if (sr == null)
    {
        return new NoSpecimen(request);
    }
    if (sr.Request != typeof(Foo))
    {
        return new NoSpecimen(request);
    }

    var foo = new Foo();
    foo.Bar = context.CreateAnonymous<int>();
    foo.Baz = context.CreateAnonymous<string>();
    return foo;
  }
}

And added the class as customization

fixture.Customizations.Add(new FooBuilder());

causing the call to CreateAnonymous<Foo> to work.

If there is a more out of the box solution, please post it and I will accept it as answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top