如何在集成测试中使用 IConfiguration?

Ste*_*ven 9 c# integration-testing unit-testing xunit asp.net-core

我有一个 API,我正在尝试使用 XUnit 对其进行一些集成测试。这是我的 API 控制器构造函数:

public class MyController : Controller
{
    readonly IMyRepository _myRepository;

    public MyController(IMyRepository myRepository)
    {
        _myRepository = myRepository;
    }

    public async Task<IActionResult> GetUser(Guid userId)
    {
        try
        {
            return Ok(await _my.GetUser(userId));
        }
        catch (Exception ex)
        {
            return StatusCode(500, "An error occurred while handling your request.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的 API 控制器正在使用这个存储库:

public class MyRepository : IMyRepository
{
    private string _connectionString;

    public MyRepository(IConfiguration config)
    {
        _connectionString = config.GetConnectionString("DefaultConnection");
    }


    public async Task<User> GetUser(Guid userId)
    {
        using (SqlConnection con = new SqlConnection(connectionString))
        {
            // call stored proc
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

存储库使用连接字符串在我的方法中进行一些数据库调用。这在我调用 API 方法时有效,因为配置是在我的 API 应用程序的 Startup 类中设置的。

但我不确定如何将带有连接字符串的配置对象从我的集成测试方法传递到我的存储库:

public async Task GetUserShouldReturnOk()
{
    var userId = new Guid();
    var configuration = // ????

    var controller = new MyController(
        new MyRepository(configuration));

    var result = await controller.GetUser(userId);

    Assert.IsType<OkResult>(result);
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试使用我的连接字符串信息将 json 设置文件添加到我的 XUnit 项目,然后尝试像我的 Startup 类那样构建它,但是我收到一个错误,因为它正在我的测试项目的 \bin\ 中寻找 json 文件Debug\netcoreapp2.0\ 目录,所以我不确定如何将基本路径指向正确的位置:

var configuration = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json")
    .Build();
Run Code Online (Sandbox Code Playgroud)

有没有合适的方法来做到这一点?

Nko*_*osi 10

appsettings.json 文件就在我的测试项目根目录中,你知道一种获取当前项目路径的简单方法,这样我就不必对该值进行硬编码

Build Action文件的属性设置为Content这样它会复制到输出目录,以便在测试时将其移动到 bin 中,然后您可以使用原始配置代码.SetBasePath(Directory.GetCurrentDirectory())

public async Task GetUserShouldReturnOk() {
    var userId = new Guid();
    var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();

    var controller = new MyController(
        new MyRepository(configuration));

    var result = await controller.GetUser(userId);

    Assert.IsType<OkResult>(result);
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*mad 9

我认为在你的测试项目中最好使用依赖注入;供将来使用。

在您的测试项目中:

  1. 将一个新的 appsettings.json 文件添加到您的测试项目中,其中包含您需要的所有配置。
  2. 安装包:Microsoft.Extensions.DependencyInjection。
  3. 为测试设置创建一个类;例如 TestSetup.cs。

    public class TestSetup
    {
        public TestSetup()
        {
            var serviceCollection = new ServiceCollection();
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile(
                     path: "appsettings.json",
                     optional: false,
                     reloadOnChange: true)
               .Build();
            serviceCollection.AddSingleton<IConfiguration>(configuration);
            serviceCollection.AddTransient<MyController, MyController>();
    
            ServiceProvider = serviceCollection.BuildServiceProvider();
        }
    
        public ServiceProvider ServiceProvider { get; private set; }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在你的测试课上;我正在使用 Xunit

    public class MyControllerTest: IClassFixture<TestSetup>
    {
        private ServiceProvider _serviceProvider;
        private MyController _myController;
    
        public MyControllerTest(TestSetup testSetup)
        {
           _serviceProvider = testSetup.ServiceProvider;
           _myController = _serviceProvider.GetService<MyController>();
        }
    
        [Fact]
        public async Task GetUserShouldReturnOk()
        {
            var result = await _myController.GetUser(userId);
            Assert.IsType<OkResult>(result);
        }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)