微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 xUnit 为使用 Entity Framework Core 和 Simple Injector 构建的 Asp.NetCore WebAPI 构建测试?

如何解决如何使用 xUnit 为使用 Entity Framework Core 和 Simple Injector 构建的 Asp.NetCore WebAPI 构建测试?

我使用 Entity Framework Core 和 Simple Injector 创建了一个 ASP.NET Core Web API。

我想使用 xUnit 进行单元测试来测试我的控制器。

我不知道从哪里开始。我相信我必须在我的单元测试中模拟一个容器对象。

这是容器初始化的启动代码

public class Startup
{
    private Container container;
    public IConfiguration Configuration { get; }
    private IConfigurationRoot configurationRoot;    

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;

        // Build configuration info
        configurationRoot = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json",optional: true,reloadOnChange: true)
            .Build();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        InitializeContainer(); 

        services.AddSimpleInjector(container,options =>
        {
            options.AddAspNetCore()
            .AddControllerActivation();
            options.AddLogging();
        });
    }

    private void InitializeContainer()
    {
        container = new SimpleInjector.Container();
        container.Options.ResolveUnregisteredConcreteTypes = false;
        container.ConfigureServices();
    }

    public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();
        app.UseRouting();
        app.UseAuthorization();
        app.UseSimpleInjector(container);
        AppSettingsHelper.AppConfig = configurationRoot;
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

这是我的服务安装程序的代码

public static class ServicesInstaller
{
    public static void ConfigureServices(this Container container)
    {
        container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

        //Assembly.Load will not re-load already loaded Assemblies
        container.Register<IFooContext,FooContext>(Lifestyle.Scoped);
        container.Register<FooContext>(Lifestyle.Scoped);
    }
}

这是一个示例控制器:

[Route("[controller]")]
[ApiController]
public class SomeController : ControllerBase
{
    private readonly ILogger<SomeController> _logger;
    private readonly Container _container;

    public SomeController(ILogger<SomeController> p_Logger,Container p_Container)
    {
        _logger = p_Logger;
        _container = p_Container;
    }
    
    [HttpGet]
    [Route("{p_SomeId}")]
    public Some GetownerByOwnerId(Guid p_SomeId)
    {
        Some some;
        using (Scope scope = AsyncScopedLifestyle.BeginScope(_container))
        {
            var dbContext = _container.GetInstance<FooContext>();
            some  = dbContext.somes.Where(x => x.someId == p_SomeId).FirstOrDefault();
        }
        return some;
    }
}

我对使用 SimpleInjector 比较陌生。

我将如何模拟用于测试的容器?

解决方法

所提供示例中的控制器不应耦合到任何特定于容器的内容。

显式地将必要的依赖项注入控制器。

[Route("[controller]")]
[ApiController]
public class SomeController : ControllerBase {
    private readonly ILogger<SomeController> _logger;
    private readonly IFooContext dbContext;

    public SomeController(ILogger<SomeController> p_Logger,IFooContext dbContext) {
        _logger = p_Logger;
        this.dbContext = dbContext;
    }
    
    [HttpGet]
    [Route("{p_SomeId}")]
    public Some GetOwnerByOwnerId(Guid p_SomeId) {
        Some some = dbContext.Somes.Where(x => x.SomeId == p_SomeId).FirstOrDefault();
        return some;
    }
}

现在不需要模拟容器,这会被视为实现细节代码异味。

在执行单元测试时模拟依赖项抽象并验证预期行为。

控制器也应该尽可能精简,因为大多数其他横切关注点,比如确保注入的上下文是有范围的,是由框架在启动时通过配置的容器处理的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?