[英]"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.