25

我想为我的集成测试存储一个数据库连接字符串作为用户密码。我的 project.json 看起来像这样:

{
  ...

  "dependencies": {
    ...
    "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0"        
  },

  "tools": {
    "Microsoft.Extensions.SecretManager.Tools": "1.1.0-preview4-final"
  },

  "userSecretsId": "dc5b4f9c-8b0e-4b99-9813-c86ce80c39e6"
}

我已将以下内容添加到我的测试类的构造函数中:

IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .AddUserSecrets();

但是,当我运行测试时,当它到达该行时会引发以下异常:

An exception of type 'System.InvalidOperationException' occurred in Microsoft.Extensions.Configuration.UserSecrets.dll but was not handled in user code

Additional information: Could not find 'UserSecretsIdAttribute' on assembly 'dotnet-test-nunit, Version=3.4.0.0, Culture=neutral, PublicKeyToken=null'.

我是否错过了某些东西或者我试图不支持的东西?

4

4 回答 4

23

请参阅 https://patrickhuber.github.io/2017/07/26/avoid-secrets-in-dot-net-core-tests.html中的说明,特别是在 InitialiseTest 添加

// the type specified here is just so the secrets library can 
            // find the UserSecretId we added in the csproj file
            var builder = new ConfigurationBuilder()
                .AddUserSecrets<HttpClientTests>();

            Configuration = builder.Build()

但是请注意,它不允许在构建服务器上运行测试

于 2017-12-16T10:43:26.150 回答
6

Startup您必须在应用程序中指定 UserSecretsId 。

[assembly: UserSecretsId("xxx")]
namespace myapp
{
    public class Startup
    {
    ...

然后你必须.AddUserSecrets(Assembly assembly)在你的测试项目中使用重载。例子:

.AddUserSecrets(typeof(Startup).GetTypeInfo().Assembly)

来源:https ://stackoverflow.com/a/40775511/5270073

于 2017-02-21T12:34:29.067 回答
0

我的基础测试类初始化了 ConfigurationBuilder,因此了解具有 userSecretsId 的程序集更加棘手。

但是我们可以确定沿途调用的所有程序集,如下所示

    var builder = new ConfigurationBuilder()
        // NOTE: Make the appsettings optional since we might just have a appsettings.TestConfig
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{environment}.json", optional: true)
        // NOTE: This brings in the test assembly's own settings as overrides for the base and environment values
        .AddJsonFile($"appsettings.TestConfig.json", optional: true)
        .AddEnvironmentVariables();
        
    var currentAssembly = Assembly.GetExecutingAssembly();
    var callerAssemblies = new StackTrace().GetFrames()
        .Select(x => x.GetMethod().ReflectedType.Assembly).Distinct()
        .Where(x => x.GetReferencedAssemblies().Any(y => y.FullName == currentAssembly.FullName));

    UserSecretsIdAttribute attribute = null;
    foreach (var assembly in callerAssemblies)
    {
        attribute = assembly.GetCustomAttribute<UserSecretsIdAttribute>();
        if (attribute != null)
        {
            break;
        }
    }

    if (attribute != null)
    {
        var userSecrets = attribute.UserSecretsId;

        // Wire up user secrets if we have them
        if (!string.IsNullOrEmpty(userSecrets))
        {
#if NETSTANDARD2_0
            builder.AddUserSecrets(userSecrets);
#else
            builder.AddUserSecrets(userSecrets, false);
#endif
        }
    }

在我的场景中这样做的好处是,如果开发人员分配了用户密码,测试将在本地正确运行,而无需代表他们更改任何代码。

于 2021-12-18T12:44:25.333 回答
-3

对于设置,您可以使用 appsettings.json,而不是 project.json。它看起来像这样:

{
    "userSecretsId": "dc5b4f9c-8b0e-4b99-9813-c86ce80c39e6"
}

确保通过更改 project.json 将文件复制到输出:

"buildOptions": {
    "copyToOutput": "appsettings.json"
}

现在您可以像这样检索秘密:

[Fact]
public MyTest()
{
    var appSettings = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json")
        .Build();

    var secret = appSettings["userSecretsId"]
}
于 2017-01-30T21:15:13.737 回答