我有一个大型应用程序,它从配置文件中读取一些参数。
我正在为一个类编写单元测试,该类在使用参数和从配置文件中读取的值执行某些操作后生成结果:
internal static class Password
{
private static readonly byte PASSWORD_PRIVATE_KEY
= ConfigFile.ReadByte("PASSWORD_PRIVATE_KEY");
public static byte Generate(byte passwordPublicKey);
}
在我的单元测试中,我知道Password.Generate()
方法应该为给定的PASSWORD_PRIVATE_KEY
和PASSWORD_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);
}
有没有办法可以编写private static readonly
代码,所以我不必依赖任何配置文件进行测试?
答案 0 :(得分: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;
}
}
现在您的生产代码可以使用ConfigPrivateKeyProvider
,测试可以使用PrivateKeyProviderStub
。
将Password
保留为静态类有点简化。我建议将其重构为一个普通的类,如果合适的话,也可以使用单例。
另请注意,有许多测试框架可以方便地动态生成模拟和存根(例如Rhino Mocks),因此无需手动实现PrivateKeyProviderStub
。
答案 1 :(得分:2)
我不是.NET专家,所以请耐心等待。
单元测试的一个值是向您显示需要重新考虑代码。如果难以测试,则需要重写。
找出一种方法,将文件的抽象注入Password
,然后创建该抽象的模拟实现(例如,使用Moq或Rhino Mocks)。
但是现在你已经拥有了,我认为没有办法使用文件。你只需要告诉你的测试来看一个不同的文件。
希望有所帮助。
答案 2 :(得分:1)
没有。 无法访问私人领域。
对于单元测试,您通常希望访问内部资源,并且可以使用InternalsVisibleTo执行此操作。但即使私人成员保持私密。您可能希望为这些字段定义一个getter。
编辑:使用一些繁琐的语法,您可以使用PrivateObjects访问私人字段。
答案 3 :(得分:1)
如果您确实要更改私有静态只读,则仍然可以使用反射进行如下操作:
typeof(YourClassName).GetField("YourStaticReadonlyMemberName", BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, YouModifiedObject);
例如:
typeof(FileSystemService).GetField("proofedStatic", BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, mockedProofedClass);
我同意几乎不应该使用它,但是有时候如果您别无选择,您就有办法做到这一点。