2

目前我正在对某个项目进行单元测试,除了开发人员使用这样的地方之外,一切都很好:

#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# 中它们甚至不能只设置定义/未定义,所以也许我只是做错了?

4

3 回答 3

5

假设您有一定的重构空间,您可以将这些指令提取到私有或受保护的属性中,然后给自己一个挂钩来修改测试中的值。

您还可以提取对类似 的依赖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预处理器值确实设置了。

于 2012-09-25T13:31:52.257 回答
3

USING_EMULATOR项目构建设置中的条件编译符号中删除。

您还可以使用不同的条件编译符号集创建不同的构建配置。例如,Debug config 定义了 DEBUG,而 Release 则没有。这也意味着如果你想执行实际的代码,你应该运行 Release 构建,而不是 Debug 构建。

于 2012-09-25T13:28:02.553 回答
1

棘手的一个。如果您想对 . 的两侧进行单元测试,则#if必须进行两次构建 - 一个已USING_EMULATOR定义,一个未定义。

这是因为在 C# 中,当有条件地编译出代码时,就相当于它根本不存在。因此,当(在您的示例中)USING_EMULATOR定义时,它会编译为与未定义时不同的非等效程序USING_EMULATOR

因此,如果您想对两个“程序”进行单元测试,则需要对被测软件的两个不同版本进行单元测试。

根据您的场景,重组软件的某些部分可能是合适的,以便可以根据需要覆盖不同的组件,从而根据需要在不同的环境中更改行为。这样,被覆盖部分的两个实现都存在于每个构建中,并且可以使用适当结构化的单元测试进行测试。

于 2012-09-25T13:30:35.060 回答