【问题标题】:Autofixture create object with static Lazy instanciationAutofixture 使用静态延迟实例化创建对象
【发布时间】:2020-07-12 12:59:46
【问题描述】:

我正在尝试测试一个服务类,但遇到了一些困难

这个类有一个私有构造函数,所以它必须从返回一个惰性 _singleton 值的静态 Instance 属性创建。

public class MyService : IMyService
{
    private static readonly Lazy<IMyService> _singleton = new Lazy<IMyService>(() => new MyService(new InjectedService()));
    public static IPermissionService Instance = _singleton.Value;

    private readonly IInjectedService _injectedService;

    private MyService(IInjectedService injectedService) => _injectedService = injectedService;


    // instance method I want to test
    public void DoSomething()
    {

    }
}

我正在尝试使用 AutoFixture 和 AutoMoq 创建我的对象,使用 Create() 方法,但它一直抱怨我没有公共构造函数。如果我将此构造函数设置为 public,我仍然会收到一个似乎来自 Lazy func 的错误。

有人可以帮忙吗?我可能有不同类型的设计问题。不知道能不能轻松解决。

编辑 1: 我没有任何 IoC 容器,因此我可以将我的服务注册为单例。 我试图使用这种方法来模拟依赖服务的注入,这样我就可以用 mocks 编写测试了。

我已经取得了一些进展,但我也不确定我是否喜欢它......无论如何我会分享我所拥有的

public static class My
{
    private static readonly Lazy<IMyService> _singleton = new Lazy<IMyService>(() => new MyService(new InjectedService()));
    public static IPermissionService Service = _singleton.Value;
}

public class MyService : IMyService
{
    private readonly IInjectedService _injectedService;

    public MyService(IInjectedService injectedService) => _injectedService = injectedService;


    // instance method I want to test
    public void DoSomething()
    {

    }
}

这样我可以使用 AutoFixture 构建我的类并冻结注入服务的模拟。

我可以这样使用静态类

My.Service.DoSomething();

在我的测试中

Fixture.Freeze<Mock<IInjectedService>>().Setup(...);
var service = Fixture.Create<MyService>();

service.DoSomething();
// assert my things

【问题讨论】:

  • 我找到了a similar question。我建议使用依赖注入并将 MyService 注册为单例。
  • 请分享minimal reproducible example 到目前为止您的(AutoFixture)进度。
  • 您使用的是哪个 IoC 容器?
  • 我实际上在这个项目中没有任何容器,并且需要付出很大的努力才能添加一个,因此 Instance 属性
  • 我在两个类中做了一些进展,一个是静态元素,一个是服务类,一个公共构造函数

标签: c# autofixture automoq


【解决方案1】:

它不像你可能喜欢的那样使用自动模拟容器,但是属性(混蛋)注入应该能让你到达那里。

根据访问要求,将静态属性标记为 internal 可能会或可能不会帮助未来的读者,但由于您可以很快做出更改,从而允许在单例模式之外创建实例类,看起来好像您会很好的。

如果您添加一个静态属性,通过该属性可以注入依赖项,您可以更改单例初始化程序以使用其值(混蛋注入:如果有的话)。

public class MyService : IService
{
  private static readonly Lazy<IService > _singleton = new Lazy<IService >(() => new 
  MyService(MyDependency ?? new BastardizedInjectable()));
  public static IService Instance = _singleton.Value;

  internal static IMyDependency MyDependency 
  { 
    get;
    set;
  }

  private readonly IMyDependency _injectedService;

  private MyService(IMyDependency injectedService) => _injectedService = injectedService;


  // instance method I want to test
  public void DoSomething()
  {
    var stuff = _injectedService.GetStuff();
  }
}

通过此实现,您的测试应该能够执行以下操作:

fixture.Customize<MyService>(c => c.FromFactory(() => MyService.Instance));
var depMock = fixture.Freeze<Mock<IMyDependency>>();
MyService.MyDependency = depMock;
var sut = fixture.Create<MyService>();

混蛋注入通常被称为反模式,或者至少与 SOLID(依赖反转)中的 D 相悖。如果您确信可以依赖此属性从comp-root 注入,那么您应该硬着头皮删除?? new BastardizedInjectable()。未来你会感谢你的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 2020-09-12
    • 1970-01-01
    • 2019-07-15
    • 2022-08-22
    相关资源
    最近更新 更多