目前我正在对某个项目进行单元测试,除了开发人员使用这样的地方外,一切都很好:
#if USING_EMULATOR
{ do nothing }
#else
{ do a lot of things }
#endif
或
#if USING_EMULATOR
return;
#endif
{ do a lot of things }
我认为USING_EMULATOR
下的代码是出于调试目的而完成的。有时也出现#if DEBUG
。如果现在仅用于调试目的的代码试图执行,我该如何检查实际代码?
#undef USING_EMULATOR
无济于事。我不太明白预处理器常量,在C#中它们甚至不能只设置定义/未定义所以也许我只是做错了?
答案 0 :(得分:3)
假设你有一些重构的自由度,你可以将这些指令提取到私有或受保护的属性中,然后给自己一个钩子来修改测试中的值。
您还可以提取IRuntimeConfiguration
之类的依赖关系,然后您可以用存根替换测试。
例如:
public class ClassIAmTesting
{
private readonly IRuntimeConfiguration _runtimeConfig;
public ClassIAmTesting(IRuntimeConfiguration runtimeConfig)
{
_runtimeConfig = runtimeConfig;
}
public void MethodIWantToTest()
{
if(_runtimeConfig.IsDebug)
return;
// …
}
}
public interface IRuntimeConfiguration
{
bool IsDebug { get; }
bool IsUsingEmulator { get; }
}
public class RuntimeConfiguration : IRuntimeConfiguration
{
public bool IsDebug
{
get
{
return
#if DEBUG
true;
#else
false;
#endif
}
}
// repeat for IsUsingEmulator
}
通过这种方式,运行代码的“选择”不是基于预处理程序指令,而是基于常规bool
属性的值。如果替换始终返回IRuntimeConfiguration
的其他false
实现,即使预处理器值确实已设置,也可以执行代码,就好不在DEBUG
而不是USING_EMULATOR
中执行。< / p>
答案 1 :(得分:2)
从项目构建设置中的条件编译符号中删除USING_EMULATOR
。
您还可以使用不同的条件编译符号集创建不同的构建配置。例如。 Debug配置定义DEBUG,而Release不定义。这也意味着如果要执行实际代码,则应运行Release构建,而不是Debug构建。
答案 2 :(得分:1)
棘手的一个。如果您想对#if
的两边进行单元测试,则必须进行两次构建 - 一次定义USING_EMULATOR
,另一次不定。
这是因为在C#中,当有条件地编译出代码时,它等同于它根本不存在。因此,当(在您的示例中)定义USING_EMULATOR
时,它会编译为不同的非等效程序,以便在未定义USING_EMULATOR
时。
因此,如果您想对两个“程序”进行单元测试,则需要对两个不同版本的被测软件进行单元测试。
根据您的方案,重新组织软件的某些部分可能是合适的,这样可以根据需要覆盖不同的组件,以根据不同环境的需要更改行为。这样,被覆盖部分的两种实现都存在于每个构建中,并且可以使用适当结构化的单元测试进行测试。