是否可以在不创建全局变量的情况下对客户端 javascript 进行单元测试?

Is it possible to unit test client side javascript without creating a global variable?

我正在尝试用 jasmine 为客户端编写单元测试 javascript。

通常我将客户端 javascript 包装在像这样的匿名函数中

(function(){ 
            // my code
           })()

我遇到的问题是我找不到让 Jasmine 可以访问它的方法。有没有办法让 "my code" 可供 jasmine 进行测试而不用像这样

var foo = function(){
                      //my code
                     }
foo()

如果您希望任何外部代码(不仅仅是 Jasmine)能够使用您编写的任何部分,它必须在某种程度上是全局的。这并不意味着您必须公开每个变量和函数,但与任何软件模块一样,任何旨在 public 可用的东西都必须公开。

例如,如果您有以下代码:

var purchaseAmount = 50;
var taxRate = 0.08;

function CalculateBill() {
    return purchaseAmount + ComputeTax();
}

function ComputeTax() {
    return purchaseAmount * taxRate;
}

您的第一种方法会隐藏所有这些,以免在其他任何地方使用:

(function () {
    //Everything from the previous code sample

    alert(CalculateBill());
})();

//Jasmine has no access to CalculateBill()

你可以做的是创建一个 class 只公开应该需要的内容 public:

function FinancialCalculator(taxRate) {
    function ComputeTax(purchaseAmount) {
        return purchaseAmount * taxRate;
    }

    this.CalculateBill = function(purchaseAmount) {
        return purchaseAmount + ComputeTax(purchaseAmount);
    }
}

Jasmine 可以做这样的事情:

describe("Financial Calculator", function() {
    it("Calculates the bill correctly", function() {
        expect(new FinancialCalculator(0.08).CalculateBill(50)).toEqual(54);
    });
});

虽然 ComputeTax() 和其他底层实现细节仍然隐藏。

如果 class 不适合您的情况,您可以改用单个全局对象,该对象同样准确地公开了 public 所需要的内容。这是 jQuery 和 Knockout.js 分别对 $ko 采取的方法。