Create a concrete type for an abstract property depending on context

I have the following type hierarchy:

public abstract class ResourceId
{
}

public class CarId : ResourceId
{
}

public class PlaneId: ResourceId
{
}

public interface IResource
{
  ResourceId Id { get; set; }
}

public class Plane : IResource
{
  public ResourceId Id { get; set; }
}

public class Car : IResource
{
  public ResourceId Id { get; set; }
}

I want AutoFixture to create the β€œright” ResourceId type when it tries to create a plane or car.

I tried using:

_fixture.Customize<Plane>(composer => 
    composer.With(h => h.Id, _fixture.Create<PlaneId>()));

But, of course, the same identifier is created for each instance. I want everyone to have a unique identifier.

What is the best approach for this?

+4
source share
3 answers

There is a way to do what you ask, but it requires less known API settings: Register.

Register - factory . AutoFixture .

Register , factory , . . :

  • Register<T>(Func<T> factory) factory
  • Register<T1, T>(Func<T1, T> factory) T1 T
  • Register<T1, T2, T>(Func<T1, T2, T> factory) T1 T2 T

, Car Plane CarId PlanId Id:

[Fact]
public void Test()
{
    var fixture = new Fixture();
    fixture.Register<CarId, Car>(id =>
    {
        var resource = new Car { Id = id };
        return resource;
    });
    fixture.Register<PlaneId, Plane>(id =>
    {
        var resource = new Plane { Id = id };
        return resource;
    });

    Assert.NotSame(fixture.Create<Car>().Id, fixture.Create<Car>().Id);
    Assert.NotSame(fixture.Create<Plane>().Id, fixture.Create<Plane>().Id);
}

, CarId PlanId, factory, AutoFixture, .

+4

, :

[Fact]
public void HowToUseFixtureToCreatePlanesWithNewIds()
{
    var fixture = new Fixture();
    fixture.Customize<Plane>(c => c
        .Without(p => p.Id)
        .Do(p => p.Id = fixture.Create<PlaneId>()));

    var planes = fixture.CreateMany<Plane>();

    Assert.True(planes.Select(p => p.Id).Distinct().Count() > 1);
}

, , ...

+4

Car Plane, :

[Fact]
public void Test()
{
    var fixture = new Fixture();
    fixture.Customize<Plane>(c => c
        .With(x => x.Id, fixture.Create<PlaneId>()));
    fixture.Customize<Car>(c => c
        .With(x => x.Id, fixture.Create<CarId>()));

    var plane = fixture.Create<Plane>();
    var car = fixture.Create<Car>();

    Assert.IsType<PlaneId>(plane.Id);
    Assert.IsType<CarId>(car.Id);
}
+1

All Articles