簡體   English   中英

根據上下文為抽象屬性創建具體類型

[英]Create concrete type for abstract property depending on context

我有以下類型層次結構:

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; }
}

我希望AutoFixture在嘗試創建Plane或Car時創建“正確”類型的ResourceId。

我試過用:

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

但是,當然會為每個實例創建相同的ID。 我希望每個人都有一個唯一的ID。

對此最好的方法是什么?

這是一個簡單的方法來做你想要的:

[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);
}

但是,如果我是你,我會認真考慮簡化那個類層次結構......

有一種方法可以滿足您的要求,但它需要一種鮮為人知的自定義API: Register方法。

Register的目的是允許用戶為特定類型指定工廠功能 然后,AutoFixture將該類型對象的創建委托給該函數。

Register一個顯着特點是它能夠提供匿名對象,以便在需要時將其作為參數傳遞給工廠函數 它通過一些重載來實現。 以下是一些示例

  • Register<T>(Func<T> factory)不向Register<T>(Func<T> factory)提供任何參數
  • Register<T1, T>(Func<T1, T> factory)提供一個T1類型的參數來創建T類型的對象
  • Register<T1, T2, T>(Func<T1, T2, T> factory)提供T1T2類型的兩個參數來創建T類型的對象

現在,我們可以使用此功能通過將CarIdPlanId匿名實例分配給其Id屬性來自定義CarPlane類型的對象:

[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);
}

此測試通過,因為傳遞給工廠函數的CarIdPlanId對象是由AutoFixture創建的 ,因此每次都不同。

您必須為每個類自定義創建算法,在此示例中為CarPlane ,如以下傳遞測試所示:

[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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM