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

How can I use IConfiguration from my integration tests?

我有一个 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.");
        }
    }
}

我的 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
        }
    }
}

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

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

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);
}

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

var configuration = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appsettings.json")
    .Build();

有正确的方法吗?

The appsettings.json file is just in my test project root, do you know an easy way to get the current project path so that I don't have to hard-code that value

将文件的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);
}

我认为在你的测试项目中使用依赖注入会更好;以备将来使用。

在您的测试项目中:

  1. 向您的测试项目添加一个新的 appsettings.json 文件,其中包含您需要的所有配置。
  2. 安装包:Microsoft.Extensions.DependencyInjection。
  3. 为测试设置创建一个class;例如 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; }
    }
    
  4. 在你的测试中class;我正在使用 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);
        }
    
    }