Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easy way to specify the value of a single constructor parameter?

Tags:

c#

autofixture

Is there some easy way in Autofixture to new-up an object using it's constructor, but hard-code/specify the value to use for a single parameter in the constructor?

I see that this can be done with properties, using something like:

fixture.Build<MyObj>().With(x=x.Val,"hard coded value").Create()

like image 803
SFun28 Avatar asked Feb 05 '15 17:02

SFun28


People also ask

How to pass constructor as parameter in Java?

Constructors can be passed as arugments to methods using a method reference, somewhat like a function pointer in C++. This can be a Function type with one argument or a BiFunction type with two arguments, either way its a lambda returning a class of the type it constructs.

What are parameters in a constructor?

A parameterized constructor accepts parameters with which you can initialize the instance variables. Using parameterized constructor, you can initialize the class variables dynamically at the time of instantiating the class with distinct values.

How many maximum parameters we can use with difficult constructor?

Sometimes overloaded constructors are also used. But Checkstyle points out that the maximum number of arguments given to a method or constructor must be 7.


1 Answers

From the discussion about this question in the comments:

Often I want to new-up an object, but I'm only concerned about a single parameter. Maybe the parameter value drives a calculation or transform of some sort. I want the value itself to be random, but the test needs to know what random value was chosen.

Assuming that this is the underlying problem, I'll attempt to address this issue.

Ask the object

The easiest solution is to simply ask the object what the value is, after AutoFixture created it:

var fixture = new Fixture();
var mc = fixture.Create<MyClass>();
var specialValue = mc.SpecialValue;
// Do something with specialValue...

If you just need to know what the special value is, but you don't need it to have a particular value, you can use this technique.

This obviously requires you to expose the value from the constructor parameter as a (read-only) property, but that's a good idea to do anyway.

Assign the value after creation

If you need the parameter to have a specific value, you can assign it after creation:

var fixture = new Fixture();
var mc = fixture.Create<MyClass>();
mc.SpecialValue = "Some really special value";

This requires you to make the value available as a writeable property. While I'm personally not a big fan of that, because that makes the object mutable, many people already design their objects that way, and if that's the case, why not take advantage of it?

Use copy-and-update after creation

If you want your objects to be immutable, you can still use a variation of the above technique. In F#, you can use so-called copy and update expressions to achieve the same goal. In F#, it'd be something like:

let fixture = Fixture ()
let mc = {
    fixture.Create<MyRecord> ()
    with SpecialValue = "Some special value!" }

You can emulate this in C# by giving your classes copy-and-update methods, so you'd be able to write something like this:

var fixture = new Fixture();
var mc = fixture
    .Create<MyClass>()
    .WithSpecialValue("Some really special value");

This is a technique I use all the time in my C# code. AutoFixture has an idiomatic assertion to test such copy and update methods.

Inject a value for a parameter

If you can live with injecting a fixed value for a particular constructor parameter, you can do this with the building blocks of the AutoFixture kernel. This test demonstrates how:

[Fact]
public void CustomizeParameter()
{
    var fixture = new Fixture();
    fixture.Customizations.Add(
        new FilteringSpecimenBuilder(
            new FixedBuilder("Ploeh"),
            new ParameterSpecification(
                typeof(string),
                "specialValue")));

    var actual = fixture.Create<MyClass>();

    Assert.Equal("Ploeh", actual.SpecialValue);
}

However, this causes that parameter to always be "Ploeh" for that fixture instance. It's also refactoring-unsafe, since it's base on a string referring to the name of the parameter.

like image 128
Mark Seemann Avatar answered Sep 19 '22 15:09

Mark Seemann