摩卡范围功能未定义

时间:2017-06-26 20:17:21

标签: javascript node.js scope mocha javascript-objects

我目前正在使用Javascript进行一些TTD教程,并且我有一个似乎是Javascript而不是TTD问题。

即,我有以下测试:

'use strict';
var chai = require('chai');
var expect = chai.expect;
var sinon = require('sinon');
var orderSystemWith = require('../lib/orders');


//describe is used to display features
//context is used to display scenarios
//it is used to describe tests within a feature/scenario
describe('Customer displays order', function () {
    beforeEach(function(){
        this.orderDAO = {
            byId: sinon.stub()
        };
        this.orderSystem = orderSystemWith(this.orderDAO);
    })

    context('Given that the order is empty', function(){
        beforeEach(function(){
            this.orderId = 'some empty order id';
            this.orderDAO.byId.withArgs(this.orderId).returns([]);
            this.result = this.orderSystem.display(this.orderId);
        })
        it('will show no order items', function(){
            expect(this.result).to.have.property('items').that.is.empty;
        });
        it('will show 0 as the total prince', function(){
            expect(this.result).to.have.property('totalPrice').that.is.equal(0);
        });
        it('will only be possible to add a beverage', function(){
            expect(this.result).to.have.property('actions').that.is.deep.equal([{
                action:'append-beverage',
                target: this.orderId,
                parameters: {
                    beverageRef: null,
                    quantity: 0  
                } 
            }])
        });
    });
});

orders.js看起来像这样:

module.exports = function(orderDAO){
    this.display = []
}

当我运行测试时,出现以下错误:

1) Customer displays order Given that the order is empty "before each" hook for "will show no order items":
     ReferenceError: orderSystem is not defined
      at Context.<anonymous> (test/customer_displays_order.js:22:27)

错误引用的行是这一行:

this.result = this.orderSystem.display(this.orderId);

有人能告诉我我做错了什么吗?在我看来,这是一个范围问题......

2 个答案:

答案 0 :(得分:3)

在mocha中,描述块是对象。当您为this分配内容时,我们的想法是为该对象分配属性。由于内部描述块(上下文块是同一个东西)正在创建一个新的上下文,它还没有导致它抛出的orderSystem属性。

在内部块上使用箭头功能或绑定可能会解决您的问题。我倾向于发现当我有这样的嵌套块时,使用作用于外部块的变量有点干净。

答案 1 :(得分:2)

跟进@aaroncrows的回答:

通过使用词汇箭头函数(ES6构造),后续描述块的范围可以访问外部描述块的上下文(&#39; this&#39;)。这是带有词汇箭头功能的代码。

    describe('Customer displays order', function () {
    beforeEach( () => {
        this.orderDAO = {
            byId: sinon.stub()
        };
        this.orderSystem = orderSystemWith(this.orderDAO);
    })

    context('Given that the order is empty', () => {
        beforeEach( () => {
            this.orderId = 'some empty order id';
            this.orderDAO.byId.withArgs(this.orderId).returns([]);
            this.result = this.orderSystem.display(this.orderId);
        })
        it('will show no order items', () => {
            expect(this.result).to.have.property('items').that.is.empty;
        });
        it('will show 0 as the total prince', () => {
            expect(this.result).to.have.property('totalPrice').that.is.equal(0);
        });
        it('will only be possible to add a beverage', () => {
            expect(this.result).to.have.property('actions').that.is.deep.equal([{
                action:'append-beverage',
                target: this.orderId,
                parameters: {
                    beverageRef: null,
                    quantity: 0  
                } 
            }])
        });
    });
});

如果您不熟悉箭头功能,我强烈建议您进行更深入的解释。请注意,通过使用箭头功能,您的上下文(或&#39;此&#39;)指的是其内部的最高范围。在这种情况下,它是您描述块的匿名函数声明(即第一行代码)。但是,当访问这个&#39;在没有嵌套在功能块中的词法箭头函数中,您可能正在访问全局上下文(例如,如果您的代码在浏览器中执行,则为Window对象)。

希望有所帮助!