سؤال

I have just started using AutoFixture, and i am getting the basics down (from what i can see there is much more to it) but i am having an issue and i am not 100% sure what the best practice is for stuff like this.

I am testing a controller, and part of the process is the action can return one of two views.

  • If a category has children - show the category listing view
  • If a category does not have children show the product listing view

So i am thinking of a few tests for that behavior, but the fixture data returned would be different. One would return a count of 0, the other a greater count then zero, so i would like the fixture to help me with that.

I have been looking around, and maybe i have to create a customisation of some sort, but was hoping the basic API could help me here. I tried this:

var category = _fixture.Build<Category>()
    .Do(x => x.SubCategories = _fixture.CreateMany<Category>(3).ToList())
    .Create();

_fakeCategoryService
    .Setup(x => x.GetById(id))
    .Returns(category);

This compiles and tests run (and fail), but the sub categories always has a count of 0, so i am thinking my call to Create Many in the do is all wrong (it kinda looks wrong but i am still unsure what it should be replaced with).

UPDATE: should read the cheat sheet a bit better!

var category = _fixture.Build<Category>()
    .With(x => x.SubCategories, _fixture.CreateMany<Category>(3).ToList())
    .Create();

This works, if there is a better way please let me know.

هل كانت مفيدة؟

المحلول

Yes, Build is correct.


If you want to customize the creation algorithm for a single Category use Build:

var actual = fixture
    .Build<Category>()
    .With(x => x.SubCategories, 
        fixture.CreateMany<Category>().ToList())
    .Create();

Assert.NotEmpty(actual.SubCategories);

If you want to customize the creation algorithm for all Category instances use Customize:

fixture.Customize<Category>(c => c
    .With(x => x.SubCategories,
        fixture.CreateMany<Category>().ToList()));

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

Assert.NotEmpty(actual.SubCategories);

نصائح أخرى

was hoping the basic API could help me here

It does help you, if you know how to listen :) AutoFixture was originally build as a tool for Test-Driven Development (TDD), and TDD is all about feedback. In the spirit of GOOS, you should listen to your tests. In this case it's saying the same as the Framework Design Guidelines:

DO NOT provide settable collection properties.

Instead of assigning a list wholesale to a property, consider

  • making the collection property read-only, and let clients invoke Add, etc.
  • taking the collection as a constructor parameter instead of mutating property

In the latter case, AutoFixture will automatically provide a populated collection when it invokes the constructor, although in this particular case, since you have a potentially recursive graph, you may need to explicitly handle it.

In the first case, AutoFixture doesn't do anything out of the box, but has an AddManyTo extension method, enabling you to fill a collection in a single statement:

fixture.AddManyTo(category.SubCategories);

You can do this stub with a custom list:

var stub = _fixture.Build<Entity>().With(x=> x.field, config).CreateMany().ToList();

Documentation.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top