语境
.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:无法实例化类的代理:WeatherManagerDataDownloader.WeatherDbContext。找不到与给定参数匹配的构造函数:
请注意,为了清楚起见,我已经简化了代码。我在模拟其他注入 DataDownloader 的服务,但我不是在模拟 dBContext。编辑:我现在已经添加了完整的代码,因为有人指出,即使我的简化代码没有暗示,模拟似乎正在发生。
问题
为什么会发生此测试异常?正如我所看到的,模拟应该与传入的 dBContext 无关。