修改私有静态只读字段

J.A*_*.L. 5 c# unit-testing

我有一个大型应用程序从配置文件中读取一些参数.

我正在为一个类编写单元测试,该类在使用参数和从配置文件读取的值执行某些操作后生成结果:

internal static class Password
{
    private static readonly byte PASSWORD_PRIVATE_KEY
        = ConfigFile.ReadByte("PASSWORD_PRIVATE_KEY");

    public static byte Generate(byte passwordPublicKey);
}
Run Code Online (Sandbox Code Playgroud)

在我的单元测试,我知道该值Password.Generate()方法应该返回给定PASSWORD_PRIVATE_KEYPASSWORD_PUBLIC_KEY.但是我喜欢PASSWORD_PRIVATE_KEY在单元测试类中定义值,而不是在配置文件中:

[TestMethod]
public void PasswordGenerate_CalculatedProperly()
{
    byte passwordPublicKey = 0x22;
    Password_Accessor.PASSWORD_PRIVATE_KEY = 0xF0;
    byte expectedGenerated = 0xAA;

    byte generated = Password_Accessor.Generate(passwordPublicKey);

    Assert.AreEqual(expectedGenerated, generated);
}
Run Code Online (Sandbox Code Playgroud)

有没有办法可以编写private static readonly直通代码,所以我不必依赖任何配置文件进行测试?

Bar*_*zKP 7

要以干净的方式进行,您需要使其Password更加可测试.为此,请考虑以下设计:

internal static class Password
{
    public static void Configure(IPrivateKeyProvider keyProvider)
    {
        keyProvider = keyProvider;
    }

    public static byte Generate(byte passwordPublicKey); // use keyProvider

    private static IPrivateKeyProvider* keyProvider;
}

internal interface IPrivateKeyProvider
{
    byte GetPrivateKey();
}

internal class ConfigPrivateKeyProvider : IPrivateKeyProvider
{
    private static readonly byte PASSWORD_PRIVATE_KEY
         = ConfigFile.ReadByte("PASSWORD_PRIVATE_KEY");

    public byte GetPrivateKey()
    {
        return PASSWORD_PRIVATE_KEY;
    }
}

internal class PrivateKeyProviderStub : IPrivateKeyProvider
{
    public PrivateKeyProviderStub(byte privateKey)
    {
        this.privateKey = privateKey;
    }

    public byte GetPrivateKey()
    {
        return this.privateKey;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你的生产代码可以使用ConfigPrivateKeyProvider和测试可以使用了PrivateKeyProviderStub.

保留Password为静态类有点简化.我建议将其重构为一个普通的类,如果合适,也可以使用单例.

另请注意,有许多测试框架可以方便地动态生成模拟和存根(例如Rhino Mocks),因此不需要手动实现PrivateKeyProviderStub.