How to tell Autofixture to create objects with different ID?
Asked Answered
D

1

9

i have a simple Setup method in my tests thats creates two instances of an object (make by and Id and a Description properties) and i have done it with autofixture:

MyObject o1 = fixture.Create<MyObject>();
MyObject o2 = fixture.Create<MyObject>();

next i try to save objects to db but i get error of duplicate key, i debug the setup and see that o1 and o2 have the same Id

According to Wiki, number should be generate progressivly:

Autogenerated Number

int autoGeneratedNumber = fixture.Create<int>();

Sample Result

int: 1, followed by 2, then by 3, etc.

but seem id does not work in this way with object property so now i use this simple workaround:

MyObject o1= fixture.Build<MyObject>().With(x => x.Id, 1).Create();
MyObject o2= fixture.Build<MyObject>().With(x => x.Id, 2).Create();

but don't like it very much

is here a way to use ISpecimenBuilder for setting up Autofixture to make it generate progressive id?

Some more info:

this is my base test class:

public class BaseDBTest
{       
    public BaseDBTest()
    { }
    public Ploeh.AutoFixture.Fixture fixture { get { return new Fixture(); } }
}

and test setup:

[TestFixture]
public class MyObjectTests : BaseDBTest
{
    MyObject o1;
    MyObject o2;

    [TestFixtureSetUp]
    public void CreaDati()
    {
        o1= fixture.Create<MyObject >();
        o2= fixture.Create<MyObject >();
    }
}

strange things is:

if I debug of the specific test objects are created with different id and random, but if I debug of all the tests of my project (with visual studio 2013 using Nunit runner) id's are created equal

EDIT2

MyObject definition, quite complex, sorry:

public class MyObject: LookUpObject<MyObject, int>
{
}

public abstract class LookUpObject<TObject, TKeyType> : EquatableObject<TObject>,     IKeyedEntity<TKeyType>
    where TObject : class
    where TKeyType : struct
{
    private TKeyType id;
    private string description;
    private bool isValid;

    public virtual TKeyType Id
    {
        get { return id; }
        set { id = value; }
    }

    public virtual string Description
    {
        get { return description; }
        set { description= value; }
    }
    public virtual bool IsValid
    {
        get { return isValid; }
        set { isValid= value; }
    }

    protected LookUpObject()
    {           
    }
}

EDIT 3

image of the strange things make with Nunit (I was afraid it might depend on Visual Studio),

single test run link

project test run link

Delossantos answered 21/8, 2014 at 9:25 Comment(10)
Did you by any chance freeze an int before creating those two objects?Press
can you explain it better? thinkDelossantos
Using AutoFixture 3.20.0, I can't reproduce your issue. The Ids are not sequential, but they're not equal either. They seem to be random integers: dotnetfiddle.net/jnSaeZPress
Did you do something like this: fixture.Freeze<int>() or fixture.Freeze(20), or did you decorate any of the tests' arguments with the [Frozen] attribute?Press
not always the case: if I debug of the specific test objects are created with different id and random, but if I debug of all the tests of my project (with visual studio 2013 using Nunit runner) id's are created equal. i never use FreezeDelossantos
question edited with complete codeDelossantos
Can you provide the source code for MyObject class?Nunnally
done, even it's quite complex and translate now from my italian object class to english generic oneDelossantos
the image of error during debug test. object are with italian name but Persona is MyObject in the code above cubeupload.com/im/JYd8jH.jpg as tell before the error rais only when debugging all tests of my project, running a single test method or a single class works fineDelossantos
i added image of test run directly with Nunit. all error you see is caused by duplicate id, all test singly worksDelossantos
C
9

This is because in your base class property to get the Fixture, you are returning a new Fixture object every time. The auto generation of Ids can only be guaranteed per Fixture instance.

Change this:

public class BaseDBTest
{       
    public BaseDBTest()
    { }
    public Ploeh.AutoFixture.Fixture fixture { get { return new Fixture(); } }
}

to this:

public class BaseDBTest
{     
    private Fixture _fixture = new Fixture();
    public BaseDBTest()
    { }
    public Ploeh.AutoFixture.Fixture fixture { get { return _fixture; } }
}
Clute answered 21/8, 2014 at 11:12 Comment(2)
great, in fact, that was really stupid return with "new" :) I focused too much on the fact that the single test (with two calls) workedDelossantos
You won't be the first or last to make that assumption ;)Clute

© 2022 - 2024 — McMap. All rights reserved.