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

1

7

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?

Strahan answered 10/10, 2013 at 3:17 Comment(2)
What does the Foo class look like?Essam
@MarkSeemann I've expanded the example using the Foo to make it a bit clearer. If you meant the actual class in my real-life project for which Foo is a proxy, it's much the same: just a POCO with gettable/settable string, int, DateTime fields.Strahan
E
12

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.

Essam answered 10/10, 2013 at 6:58 Comment(2)
Yes, that was the strategy I ended up using. I realise from the discussion at your link that this use case diverges from the core intention of AutoFixture. I just got used to NBuilder's delicious syntactic sugar... sugar which I suspect I can implement myself on top of IEnumerable<T> if I really want that 'fluent' feel to my code.Strahan
Neat solution. IMHO, I still think it would be nice if this was built in.Tetrabrach

© 2022 - 2024 — McMap. All rights reserved.