Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
276 views
Welcome To Ask or Share your Answers For Others

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...