Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I assign a property on only a subrange of items in a list?

I want to create a list of custom objects using AutoFixture. I want the first N objects to have a property set to one value, and the remainder to have it set to another value (or to simply be set by the Fixture's default strategy).

I am aware that I can use Fixture.CreateMany<T>.With, but this applies a function to all members of the list.

In NBuilder there are methods named TheFirst and TheNext (among others) which provide this functionality. An example of their use:

Given a class Foo:

class Foo
{
    public string Bar {get; set;}
    public int Blub {get; set;}
}

one can instantiate a bunch of Foos like so:

class TestSomethingUsingFoo
{
    /// ... set up etc.

    [Test]
    public static void TestTheFooUser()
    {
        var foosToSupplyToTheSUT = Builder<Foo>.CreateListOfSize(10)
            .TheFirst(5)
                .With(foo => foo.Bar = "Baz")
            .TheNext(3)
                .With(foo => foo.Bar = "Qux")
            .All()
                .With(foo => foo.Blub = 11)
            .Build();

        /// ... perform the test on the SUT 
    }
}

This gives a list of objects of type Foo with the following properties:

[Object]    Foo.Bar    Foo.Blub
--------------------------------
0           Baz        10
1           Baz        10
2           Baz        10
3           Baz        10
4           Baz        10
5           Qux        10
6           Qux        10
7           Qux        10
8           Bar9       10
9           Bar10      10

(The Bar9 and Bar10 values represent NBuilder's default naming scheme)

Is there a 'built-in' way to achieve this using AutoFixture? Or an idiomatic way to set up a fixture to behave like this?

like image 905
Peter Avatar asked Oct 10 '13 03:10

Peter


1 Answers

By far the easiest way to do that would be like this:

var foos = fixture.CreateMany<Foo>(10).ToList();
foos.Take(5).ToList().ForEach(f => f.Bar = "Baz");
foos.Skip(5).Take(3).ToList().ForEach(f => f.Bar = "Qux");
foos.ForEach(f => f.Blub = 11);

Assigning values to properties is already built-in to C#, so instead of providing a restrictive API that can't possibly enable you to do everything you'd want to do, the AutoFixture philosophy is to use the language constructs already available.

The next philosophical step is that if you often need to do something like that, the SUT could probably benefit from a redesign.

like image 92
Mark Seemann Avatar answered Sep 21 '22 02:09

Mark Seemann