簡體   English   中英

注入 dbContext 時返回“找不到與給定參數匹配的構造函數”

[英]"Could not find a constructor that would match given arguments" returned when injecting a dbContext

語境

.NET 5 控制台應用程序使用 IHostedService 模式和 EntityFramework Core 5。

問題

dbContext 如下所示:

    public class WeatherDbContext : DbContext, IWeatherDbContext
    {
        public WeatherDbContext(DbContextOptions<WeatherDbContext> options) : base(options)
        {
        }

       public virtual DbSet<Observation> Observations { get; set; }
}

主機構建器是這樣配置的:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
        })
        .UseSerilog((hostContext, loggerConfiguration) =>
        {
            logConfiguration.WriteTo.File(ConfigurationManager.AppSettings["LogFile"]);
        })
        .ConfigureServices((services) =>
        {
            services.AddHttpClient()
                    .AddSingleton<CommandLineArguments>(new CommandLineArguments(args))
                    .AddSingleton<StringWriter>()
                    .AddDbContext<IWeatherDbContext, WeatherDbContext>(options =>
                    {
                        options.UseSqlServer(ConfigurationManager.ConnectionStrings["WeatherManagerDatabase"].ConnectionString);
                    })   
                    .AddTransient<IWeatherUndergroundAPIService(x => new WeatherUndergroundAPIService(ConfigurationManager.AppSettings["StationId"],
                                                                                                      ConfigurationManager.AppSettings["WUApiKey"],
                                                                                                      x.GetRequiredService<IHttpClientFactory>()))
                   .AddHostedService<DataDownloader>();                                                                                        
        });

...並且主機服務是這樣構造的:

private readonly int importDayLimit;
private readonly ILogger logger;
private readonly StringWriter outputWriter;
private readonly int throttleLimit = 100;
private readonly IWeatherDbContext weatherDbContext;
private readonly IWeatherUndergroundAPIService wuApiService;
private DateTime FetchUpToDate;
private DateTime MostRecentlyRecordedObservationDate;

public DataDownloader(IWeatherUndergroundAPIService wuApiService,
                      ILogger logger,
                      IWeatherDbContext weatherDbContext,
                      StringWriter outputWriter,
                      CommandLineArguments commandLineArguments)
{
    this.wuApiService = wuApiService;
    this.weatherDbContext = weatherDbContext;
    this.logger = logger;
    this.outputWriter = outputWriter;
    this.importDayLimit = this.ProcessCommandLineArguments(commandLineArguments.Args);
}

然后我有一個這樣的 XUnit 測試:

public class CommandLineArgumentValidation
{
    [Fact]
    public async Task CommandLineArgumentNotAnIntegerAsync()
    {
        // Arrange

        Mock<IWeatherUndergroundAPIService> mockWeatherUndergroundAPIService = new();

        DbContextOptions<WeatherDbContext> dbContextOptions = new DbContextOptionsBuilder<WeatherDbContext>()
            .UseInMemoryDatabase(databaseName: "testDb")
            .EnableDetailedErrors()
            .Options;

        IWeatherDbContext weatherDbContext = new WeatherDbContext(dbContextOptions);

        Mock<ILogger> mockLogger = new();
        
        StringBuilder consoleOutput = new();
        StringWriter consoleWriter = new(consoleOutput);
        
        CommandLineArguments commandLineArguments = new(new string[] { "not a positive integer" });

        DataDownloader dataDownloader = new(mockWeatherUndergroundAPIService.Object,
                                           mockLogger.Object,
                                           weatherDbContext,
                                           consoleWriter,
                                           commandLineArguments);
        
        CancellationToken cancellationToken = new(false);

        // Action

        await dataDownloader.StartAsync(cancellationToken);

        // Assertion

        Assert.Equal("Command line argument 'not a positive integer' is not a positive integer. Aborting download.", consoleOutput.ToString());
    }
}

測試拋出異常

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException:無法實例化 class 的代理:WeatherManagerDataDownloader.WeatherDbContext。 找不到與給定 arguments 匹配的構造函數:

請注意,為了清楚起見,我已經簡化了代碼。 mocking 注入到 DataDownloader 的其他服務,但我不是 mocking dBContext。 編輯:我現在已經添加了完整的代碼,因為注意到 mocking 似乎正在發生,即使我的簡化代碼沒有暗示這一點。

問題

為什么會發生此測試異常? 在我看來,mocking 應該與傳入的 dBContext 無關。

認為這可能是答案,當然它允許我繼續前進。

使用調試器運行測試時,我意識到一切都已成功注入,並且測試的代碼正在成功進行。 但是我正在測試無效的命令行參數情況,並且在 DataDownloader 中我已經編碼

Environment.Exit(1)

在輸出適當的消息后停止應用程序。 顯然,這不是您應該在 IHostedService 中執行的操作,刪除它會使 mocking 錯誤 go 消失。 然而,為什么它會導致 mocking 錯誤對於尚未被嘲笑的東西仍然令人費解。

暫無
暫無

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

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