Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining/managing >1 constructor parameters of the same type with independent values when using AutoFixture as a SutFactory

Using AutoFixture as a SutFactory, I can see that if I register or freeze a value for a type, that value will then be used for all subsequent usages of that type. However, if I have a class with two parameters that are the same type on the constructor such as:

public class ClassA
{
    public double ParameterA { get; private set;}
    public double ParameterB { get; private set;}

    public ClassA(double parameterA, double parameterB)
    {
       ParameterA = parameterA;
       ParameterB = parameterB;
    }

    public void Execute(ClassB object)
    {
        object.Value = (object.Value * ParameterA) /ParameterB;
    }
}

What strategies exist for using autofixture to inject unique pre-defined values for parameterA and parameterB with a view to testing the Calculated value?

*Unfortunately I can't share my exact scenario here, however its using the command pattern to operate on another object, so the only way of setting parameterA and parameterB maintaining the design is to inject them both in, and the constructor is the neatest way to do this in this case.

like image 519
gmn Avatar asked Jun 08 '13 08:06

gmn


3 Answers

It's my observation that most of the times when I encounter a scenario like that, I don't particularly need to control the values before they're passed to the constructor, but rather that I need to know what the values are.

That's easy to accomplish by adding Structural Inspection Properties to the class:

public class ClassA
{
    public ClassA(double parameterA, double parameterB)
    {
        this.A = parameterA;
        this.B = parameterB;
    }

    public double A { get; private set }

    public double B { get; private set }
}

Now you can ask AutoFixture to create an instance of ClassA without further ado, and subsequently query the instance about the values.

like image 67
Mark Seemann Avatar answered Nov 15 '22 18:11

Mark Seemann


One option is to customize the creation algorithm for all instances of ClassA.

var valueA = 1;
var valueB = 2;

var fixture = new Fixture();
fixture.Customize<ClassA>(c => c
    .FromFactory(() => 
        new ClassA(valueA, valueB)));

var result = fixture.Create<ClassA>();
// -> parameterA value is 1
// -> parameterB value is 2
like image 40
Nikos Baxevanis Avatar answered Nov 15 '22 16:11

Nikos Baxevanis


Having used the features a bit more, I have personally found that there are not too many objects where this happens, so creating a simple customization for the class is probably best here, e.g.:

public class ClassACustomization: ICustomization
{
    public double ParameterA { get; set;}
    public double ParameterB { get; set;}

    public void Customize(IFixture fixture)
    {
         //Note: these can be initialized how you like, shown here simply for convenience.
         ParameterA = fixture.Create<double>();
         ParameterB = fixture.Create<double>();
         fixture.Customize<ClassA>(c => c
           .FromFactory(() => 
           new ClassA(ParameterA , ParameterB )));
    }
}

I find that this still gives me the flexibility that is great about AutoFixture, without compromising on the ability to inject in specific instances of ParameterA or ParameterB (you could set them up using builder methods, constructor etc... Instead of in the customization to Random values).

like image 20
gmn Avatar answered Nov 15 '22 18:11

gmn