Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a struct with autofixture throws no public constructor error

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.

like image 655
Rok Avatar asked Oct 17 '12 09:10

Rok


1 Answers

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.

like image 132
Mark Seemann Avatar answered Sep 30 '22 13:09

Mark Seemann