9

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.

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
gmn
  • 4,199
  • 4
  • 24
  • 46

3 Answers3

6

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.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Usually I'd agree with you. In this case (which I didn't make clear in the question), I am thinking more about a situation where I have a calculation that depends on the two values that I would like to verify. I really need to know what the two arguments are to have a reasonable inputs to the calculation that I can verify. – gmn Jun 11 '13 at 19:14
  • 3
    If, for a moment, you consider the case where the dependencies aren't primitives, but interfaces, the exact value shouldn't matter; if it does, the class most likely breaks the Liskov Substitution Principle. From experience, I'm beginning to think that the same sort of principle applies to primitive dependencies. If the value matters, it's probably not a dependency. Perhaps those values are better passed as method arguments? Or perhaps it turns out that they are better modelled as interfaces or classes after all? Can you share your scenario? – Mark Seemann Jun 12 '13 at 06:20
  • I see you're point, and agree generally speaking, I've updated to be a bit more specific above if that helps shed some light on what I'm attempting to achieve. – gmn Jul 11 '13 at 20:30
5

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
Nikos Baxevanis
  • 10,868
  • 2
  • 46
  • 80
  • 2
    Just curious... Any reason you chose to highlight `Customize` rather than `Register` ? – Ruben Bartelink Jun 10 '13 at 08:30
  • No, not any special reason.. Actually, `Customize` is more explicit.. Both `Register` and `Customize` yield the same result though :) – Nikos Baxevanis Jun 10 '13 at 09:45
  • @RubenBartelink, its my understanding that register would not solve this scenario, it would simply set both of the double arguments to the same value. In the case above I really need to specify two different parameters that i can control to be injected in. Preferably whilst keeping my tests flexible for future constructor arguments. – gmn Jun 11 '13 at 19:19
  • 2
    @grrrrrrrrrrrrr Don't worry, I understand your question fine (see my link to the related answer on the Q) - I was referring to the fact that one could write Nikos' answer more briefly as `fixture.Register( () => new ClassA(valueA,valueB)`. `Customize` is more general but `Register` can in many instances be the perfect tool for the job. (`Register`'s method body consists of `fixture.Customize(c => c.FromFactory(creator).OmitAutoProperties());`) – Ruben Bartelink Jun 11 '13 at 21:00
  • @RubenBartelink Thanks that clarifies things. It didn't click that register could be used like that. – gmn Jun 11 '13 at 21:21
  • @RubenBartelink I guess whichever way its done, in this scenario you need to specify the constructor to use explicitly? – gmn Jun 11 '13 at 21:43
  • 1
    @grrrrrrrrrrrrr BTW If you wanted to specialize only `parameterA`, the `Register` syntax can only be `fixture.Register((double a)=>new ClassA(a,valueB)` or `fixture.Register(a=>new ClassA(a,valueB)` whereas `Customize` never requires redundantly stating `ClassA` - i.e., you can do `fixture.Customize(c=>c.FromFactory(a=>new ClassA(a,valueB)))`. Re having to have a ctor invocation expression, you can only avoid it by using my other customization (see link on OP) or the various flavors of same which allow one to pinpoint a specific parameter (only only that) – Ruben Bartelink Jun 11 '13 at 21:45
  • @RubenBartelink Since using AutoFixture for a while, I feel I have come up with a good compromise solution to this problem (shown by my answer). I thought I'd share this, and mark as accepted as its the most concise answer I've seen to this particular problem. Your answer did lead me to this conclusion. Thanks. – gmn Aug 13 '13 at 17:31
  • @grrrrrrrrrrrrr Yes, looks fine - as long as your tests are getting cleaner it's all good... – Ruben Bartelink Aug 20 '13 at 08:40
2

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).

gmn
  • 4,199
  • 4
  • 24
  • 46