Mocking/stubbing是否启用调试日志?

Mocking/stubbing whether or debug log is enabled?

如何编写模拟测试来验证无​​法访问的 属性 (debugLog) 是否设置为 true?我是否尝试找到一种方法来找到 属性 的值?我是否验证 console.debug 已设置?在这种情况下间谍有意义还是我应该使用存根?

Class X

let showDebugLogs = false,
debugLog = _.noop

/**
 * Configures Class X instances to output or not output debug logs.
 * @param {Boolean} state The state.
 */
exports.showDebugLogs = function (state) {
    showDebugLogs = state;
    debugLog = showDebugLogs ? console.debug || console.log : _.noop;
};

单元测试

    describe('showDebugLogs(state)', function () {
        let spy;
        it('should configure RealtimeEvents instances to output or not output debug logs', function () {
            spy = sinon.spy(X, 'debugLog');
            X.showDebugLogs(true);
            assert.strictEqual(spy.calledOnce, true, 'Debug logging was not enabled as expected.');
            spy.restore();
        });
    });

模拟测试用于 "isoloting" 一个 class 在其环境中进行测试,以减少其副作用并提高其测试能力。例如,如果您正在测试一个 class 对网络服务器进行 AJAX 调用,您可能不希望:

1) wait for AJAX calls to complete (waste of time)
2) observe your tests fall apart because of possible networking problems
3) cause data modifications on the server side

等等。

所以你要做的是 "MOCK" 你的代码的一部分,它会调用 AJAX,并且根据你的测试你可以:

1) return success and response accompanying a successful request
2) return an error and report the nature of the point of failure to see how your code is handing it.

对于您的案例,您需要的只是一个简单的单元测试用例。您可以使用内省技术断言对象的内部状态,如果这是您真正想要的。但是,这带有警告:不鼓励请看底部注释

应该进行单元测试以测试对象的行为或 public 状态。所以,你真的不应该关心 class.

的内部结构

因此,我建议您重新考虑要测试的内容,并找到更好的测试方法。

建议:除了检查 class 中的标志外,您还可以为测试模拟记录器。并至少编写如下两个测试用例:

1) When showDebugLogs = true, make sure log statement of your mock logger is fired
2) When showDebuLogs = false, log statement of your mock logger is not called. 

注释:两派人士之间存在长期争论:一个团体主张私有 members/methods 是实现细节,不应该 NOT 直接进行测试,另一组反对此想法:

Excerpt from a wikipedia article:

There is some debate among practitioners of TDD, documented in their blogs and other writings, as to whether it is wise to test private methods and data anyway. Some argue that private members are a mere implementation detail that may change, and should be allowed to do so without breaking numbers of tests. Thus it should be sufficient to test any class through its public interface or through its subclass interface, which some languages call the "protected" interface.[29] Others say that crucial aspects of functionality may be implemented in private methods and testing them directly offers advantage of smaller and more direct unit tests