获取错误以下构造函数参数没有匹配的固定数据:PostgreSqlResource资源

发布于 2025-02-07 12:59:54 字数 2215 浏览 1 评论 0原文

我正在使用Xunit进行集成测试,以下是我的测试类。

public class CodesAndGuidelinesTest : IClassFixture<SchemaCache>
{
    public readonly SchemaCache schemaCache;
    public CodesAndGuidelinesTest(PostgreSqlResource resource) 
    {
        schemaCache = new SchemaCache(resource);
    }

    [Fact]
    public async Task Create_Name_Contains_Expression()
    {
        IRequestExecutor requestExecutor = await schemaCache.CodesAndGuidelinesExecutor;
        .......
    }
}

这是此处的架构缓存类

public class SchemaCache : QueryTestBase
{
    Task<IRequestExecutor> _codesAndGuidelinesExecutor;
    public SchemaCache(PostgreSqlResource resource) : base(resource)
    {
        _codesAndGuidelinesExecutor = CreateDb(CodesAndGuidelinesMockFixture.codeStandardGuidelines);
    }

    public Task<IRequestExecutor> CodesAndGuidelinesExecutor
    {
        get { return _codesAndGuidelinesExecutor; }
    }
}

codesandguidelinesmockfixture.codestandardguidelines只是一个模拟对象,当我运行测试用例时,我会收到以下错误。

类固定装置类型'api.tests.schemacache'有一个或多个未解决的 构造函数参数:PostgreSqlresource资源, codestandardguideline [] codesandguidelines以下 构造函数参数没有匹配的固定数据: PostgreSqlresource Resource

我不确定我在哪里做错了上述代码。谁能向我指向正确的方向?

谢谢!!!

更新 : queryTestBase类

public class QueryTestBase
{
    private readonly PostgreSqlResource _resource;
    public QueryTestBase(PostgreSqlResource resource)
    {
        _resource = resource;
    }

    protected async Task<Func<IResolverContext, IQueryable<T>>> BuildResolverAsync<T>(T[] arrayOfEntities) where T : class
    {
        var databaseName = Guid.NewGuid().ToString("N");
        var options = new DbContextOptionsBuilder<APIDbContext>()
            .UseNpgsql(_resource.ConnectionString)
            .Options;
        .......
        .......         
        return _ => set.AsQueryable();
    }

    protected async Task<IRequestExecutor> CreateDb<T>(T[] Entities) where T : class
    {
        Func<IResolverContext, IQueryable<T>> resolver = await BuildResolverAsync(Entities);

        return .......
    }
}

I am using xunit to do integration testing, and below is my test class.

public class CodesAndGuidelinesTest : IClassFixture<SchemaCache>
{
    public readonly SchemaCache schemaCache;
    public CodesAndGuidelinesTest(PostgreSqlResource resource) 
    {
        schemaCache = new SchemaCache(resource);
    }

    [Fact]
    public async Task Create_Name_Contains_Expression()
    {
        IRequestExecutor requestExecutor = await schemaCache.CodesAndGuidelinesExecutor;
        .......
    }
}

Here is the schema cache class

public class SchemaCache : QueryTestBase
{
    Task<IRequestExecutor> _codesAndGuidelinesExecutor;
    public SchemaCache(PostgreSqlResource resource) : base(resource)
    {
        _codesAndGuidelinesExecutor = CreateDb(CodesAndGuidelinesMockFixture.codeStandardGuidelines);
    }

    public Task<IRequestExecutor> CodesAndGuidelinesExecutor
    {
        get { return _codesAndGuidelinesExecutor; }
    }
}

Here CodesAndGuidelinesMockFixture.codeStandardGuidelines is just a mock object, and When I run the test cases, I am getting the below error.

Class fixture type 'API.Tests.SchemaCache` had one or more unresolved
constructor arguments: PostgreSqlResource resource,
CodeStandardGuideline[] codesAndGuidelines The following
constructor parameters did not have matching fixture data:
PostgreSqlResource resource

I am not sure where I am doing wrong with the above code. Could anyone point me in the right direction?

Thanks!!!

Update :
QueryTestBase class

public class QueryTestBase
{
    private readonly PostgreSqlResource _resource;
    public QueryTestBase(PostgreSqlResource resource)
    {
        _resource = resource;
    }

    protected async Task<Func<IResolverContext, IQueryable<T>>> BuildResolverAsync<T>(T[] arrayOfEntities) where T : class
    {
        var databaseName = Guid.NewGuid().ToString("N");
        var options = new DbContextOptionsBuilder<APIDbContext>()
            .UseNpgsql(_resource.ConnectionString)
            .Options;
        .......
        .......         
        return _ => set.AsQueryable();
    }

    protected async Task<IRequestExecutor> CreateDb<T>(T[] Entities) where T : class
    {
        Func<IResolverContext, IQueryable<T>> resolver = await BuildResolverAsync(Entities);

        return .......
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷迭香的记忆 2025-02-14 12:59:54

您的工具(中队)提供了一种简便的方法,可以使postgresqlresource

此资源具有此属性:

  • 实现标准idisposable接口(或Xunit Spefic iaSynclifetime接口)
  • 具有无参数的contructor,
// sync implementation
class PostgreSqlResource : IDisposable
{
  public PostgreSqlResource()
  {
    // init code
  }

  // props and logic 

  public Dispose()
  {
    // dispose code
  }
}

// async implementation
class PostgreSqlResource : IAsyncLifetime
{
  public PostgreSqlResource()
  {
  }

  public async Task InitializeAsync()
  {
    // init code
  }

  // props and logic 

  public async Task DisposeAsync()
  {
    // dispose code
  }
}

该对象可以以3方式以Xunit共享:

  • 对于每个测试:对于每个测试:创建固定装置,执行测试,为每个班级处置固定装置
  • :创建固定装置,在类中执行测试,
  • 为一组类别处置固定装置:创建固定装置,执行标记的测试类,

在您的情况下处置固定装置,您需要第三种方式。

因此,中队为您提供固定装置,Jou只需要定义testCollection来标记您的类。

[CollectionDefinition("Squadron")]
public class DatabaseCollection : ICollectionFixture<PostgreSqlResource>
{
    // This class has no code, and is never created. Its purpose is simply
    // to be the place to apply [CollectionDefinition] and all the
    // ICollectionFixture<> interfaces.
}

之后,您可以简单地使用属性标记测试类[Collection(“ squadron”)],允许您通过构造函数进行注入共享实例。

[Collection("Squadron")]
public class DatabaseTestClass1
{
    PostgreSqlResource fixture;

    public DatabaseTestClass1(PostgreSqlResource fixture)
    {
        this.fixture = fixture;
    }
}

[Collection("Squadron")]
public class DatabaseTestClass2
{
   // ...


如果postgresqlresource还不够,您需要更复杂的固定装置非常容易;您可以在另一个方面创建自己的固定装置。

当然,您需要实现相同的接口并将实现委托给内成员。

class ComplexFixture: IAsyncLifetime
{
  private PostgreSqlResource _pg;

  public ComplexFixture()
  {
    _pg = new PostgreSqlResource();
  }

  // fixture methods

  public async Task InitializeAsync()
  {
    await _pg.InitializeAsync();
  }

  public async Task DisposeAsync()
  {
    await _pg.DisposeAsync();
  }
}

并参考复杂fixture在Xunit CollectionFixtures上设立的postgresqlresource。不建议这种方法。


在我看来,最好是注入测试课程的普通固定装置,而不是在需要的情况下包裹在类固定对象中。

[Collection("Squadron")]
public class DatabaseTestClass1 : IDisposable
{
    // each test lifecycle
    private MyComplexFixture _fixture;

                              // global lifecycle
    public DatabaseTestClass1(DatabaseFixture dbFixture)
    {
        _fixture = new MyComplexFixture(dbFixture)
    }

    // tests

    public Dispose()
    {
        // this can reset db state for a new test
        _fixture.Dispose();
    }
}

public class MyComplexFixture : IDisposable
{
    public MyComplexFixture (DatabaseFixture dbFixture)
    {
      // ...
    }

    public Dispose()
    {
       // reset logic like DROP TABLE EXECUTION

       // Please note that dbFixture shoul no be disposed here!
       // xunit will dispose class after all executions.
    }
}

因此,将此解决方案应用于您的代码可以如下。

[CollectionDefinition("SquadronSchemaCache")]
public class DatabaseCollection : ICollectionFixture<SchemaCache>
{
}

[Collection("SquadronSchemaCache")]
public class CodesAndGuidelinesTest
{
    public readonly SchemaCache schemaCache;

    public CodesAndGuidelinesTest(SchemaCache resource) 
    {
        this.schemaCache = schemaCache;
    }

    [Fact]
    public async Task Create_Name_Contains_Expression()
    {
        IRequestExecutor requestExecutor = await schemaCache.CodesAndGuidelinesExecutor;
        .......
    }
}

public class SchemaCache : QueryTestBase
{
    Task<IRequestExecutor> _codesAndGuidelinesExecutor;
    public SchemaCache() : base(new PostgreSqlResource())
    {
        _codesAndGuidelinesExecutor = CreateDb(CodesAndGuidelinesMockFixture.codeStandardGuidelines);
    }

    public Task<IRequestExecutor> CodesAndGuidelinesExecutor
    {
        get { return _codesAndGuidelinesExecutor; }
    }
}

public class QueryTestBase : IAsyncLifetime
{
    private readonly PostgreSqlResource _resource;
    public QueryTestBase(PostgreSqlResource resource)
    {
        _resource = resource;
    }

    protected async Task<Func<IResolverContext, IQueryable<T>>> BuildResolverAsync<T>(T[] arrayOfEntities) where T : class
    {
        var databaseName = Guid.NewGuid().ToString("N");
        var options = new DbContextOptionsBuilder<APIDbContext>()
            .UseNpgsql(_resource.ConnectionString)
            .Options;
        .......
        .......         
        return _ => set.AsQueryable();
    }

    protected async Task<IRequestExecutor> CreateDb<T>(T[] Entities) where T : class
    {
        Func<IResolverContext, IQueryable<T>> resolver = await BuildResolverAsync(Entities);

        return .......
    }

    public async Task InitializeAsync()
    {
      await _resource.InitializeAsync();
    }

    public async Task DisposeAsync()
    {
        _resource.Dispose()
    }
}

Your tool (Squadron) provides an easy way to have a PostgreSqlResource.

This resource has this properties:

  • implement standard IDisposable interface (or xunit speficIAsyncLifetime interface)
  • has a parameterless contructor
// sync implementation
class PostgreSqlResource : IDisposable
{
  public PostgreSqlResource()
  {
    // init code
  }

  // props and logic 

  public Dispose()
  {
    // dispose code
  }
}

// async implementation
class PostgreSqlResource : IAsyncLifetime
{
  public PostgreSqlResource()
  {
  }

  public async Task InitializeAsync()
  {
    // init code
  }

  // props and logic 

  public async Task DisposeAsync()
  {
    // dispose code
  }
}

This object can be shared in xunit in 3 way:

  • for each test: create fixture, execute test, dispose fixture
  • for each class: create fixture, execute tests inside a class, dispose fixture
  • for a set of classes: create fixture, execute marked test classes, dispose fixture

In your case you need the 3rd way.

So Squadron provide a fixture for you, jou just need to define a TestCollection to mark your classes.

[CollectionDefinition("Squadron")]
public class DatabaseCollection : ICollectionFixture<PostgreSqlResource>
{
    // This class has no code, and is never created. Its purpose is simply
    // to be the place to apply [CollectionDefinition] and all the
    // ICollectionFixture<> interfaces.
}

and after that you can simply tag your test classes with attribute [Collection("Squadron")] that allow you in inject via constructor the shared instance.

[Collection("Squadron")]
public class DatabaseTestClass1
{
    PostgreSqlResource fixture;

    public DatabaseTestClass1(PostgreSqlResource fixture)
    {
        this.fixture = fixture;
    }
}

[Collection("Squadron")]
public class DatabaseTestClass2
{
   // ...


In case PostgreSqlResource is not enought and you need a more complex fixture is very easy; you can just create your own fixture around the other.

Of course you need to implement the same interface and delegate implementation to inner member.

class ComplexFixture: IAsyncLifetime
{
  private PostgreSqlResource _pg;

  public ComplexFixture()
  {
    _pg = new PostgreSqlResource();
  }

  // fixture methods

  public async Task InitializeAsync()
  {
    await _pg.InitializeAsync();
  }

  public async Task DisposeAsync()
  {
    await _pg.DisposeAsync();
  }
}

And refer to ComplexFixture insted of PostgreSqlResource on xunit CollectionFixtures. This approach is not suggested.


In my opinion is better a Plain fixture injected to test class, and than wrapped in a class fixture object if needed.

[Collection("Squadron")]
public class DatabaseTestClass1 : IDisposable
{
    // each test lifecycle
    private MyComplexFixture _fixture;

                              // global lifecycle
    public DatabaseTestClass1(DatabaseFixture dbFixture)
    {
        _fixture = new MyComplexFixture(dbFixture)
    }

    // tests

    public Dispose()
    {
        // this can reset db state for a new test
        _fixture.Dispose();
    }
}

public class MyComplexFixture : IDisposable
{
    public MyComplexFixture (DatabaseFixture dbFixture)
    {
      // ...
    }

    public Dispose()
    {
       // reset logic like DROP TABLE EXECUTION

       // Please note that dbFixture shoul no be disposed here!
       // xunit will dispose class after all executions.
    }
}

So applying this solution to your code can be as follows.

[CollectionDefinition("SquadronSchemaCache")]
public class DatabaseCollection : ICollectionFixture<SchemaCache>
{
}

[Collection("SquadronSchemaCache")]
public class CodesAndGuidelinesTest
{
    public readonly SchemaCache schemaCache;

    public CodesAndGuidelinesTest(SchemaCache resource) 
    {
        this.schemaCache = schemaCache;
    }

    [Fact]
    public async Task Create_Name_Contains_Expression()
    {
        IRequestExecutor requestExecutor = await schemaCache.CodesAndGuidelinesExecutor;
        .......
    }
}

public class SchemaCache : QueryTestBase
{
    Task<IRequestExecutor> _codesAndGuidelinesExecutor;
    public SchemaCache() : base(new PostgreSqlResource())
    {
        _codesAndGuidelinesExecutor = CreateDb(CodesAndGuidelinesMockFixture.codeStandardGuidelines);
    }

    public Task<IRequestExecutor> CodesAndGuidelinesExecutor
    {
        get { return _codesAndGuidelinesExecutor; }
    }
}

public class QueryTestBase : IAsyncLifetime
{
    private readonly PostgreSqlResource _resource;
    public QueryTestBase(PostgreSqlResource resource)
    {
        _resource = resource;
    }

    protected async Task<Func<IResolverContext, IQueryable<T>>> BuildResolverAsync<T>(T[] arrayOfEntities) where T : class
    {
        var databaseName = Guid.NewGuid().ToString("N");
        var options = new DbContextOptionsBuilder<APIDbContext>()
            .UseNpgsql(_resource.ConnectionString)
            .Options;
        .......
        .......         
        return _ => set.AsQueryable();
    }

    protected async Task<IRequestExecutor> CreateDb<T>(T[] Entities) where T : class
    {
        Func<IResolverContext, IQueryable<T>> resolver = await BuildResolverAsync(Entities);

        return .......
    }

    public async Task InitializeAsync()
    {
      await _resource.InitializeAsync();
    }

    public async Task DisposeAsync()
    {
        _resource.Dispose()
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文