简体   繁体   English

摩卡范围功能未定义

[英]Mocha Scope Function Undefined

I am currently going through some TTD tutorials using Javascript and am having a what seems to be a Javascript rather than a TTD problem. 我目前正在阅读一些使用Javascript的TTD教程,并且遇到了似乎是Javascript而不是TTD的问题。

Namely, I have the following tests: 即,我有以下测试:

'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  
                } 
            }])
        });
    });
});

The orders.js looks like this: orders.js如下所示:

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

When I run the tests, I get the following error: 运行测试时,出现以下错误:

 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) 

The line to which the error refers is this one: 错误所指向的行是这一行:

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

Could someone tell me what I am doing wrong? 有人可以告诉我我在做什么错吗? It seems to me that it is a scope issue ... 在我看来,这是一个范围问题...

In mocha the describe blocks are objects. 在摩卡咖啡中,描述块是对象。 When you assign something to this the idea is to assign a property to that object. 当您this分配某些内容时,其想法是为该对象分配一个属性。 Since the inner describe block (the context block it's the same thing) is creating a new context it doesn't yet have an orderSystem property which is causing it to throw. 由于内部describe块(上下文块是同一件事)正在创建新的上下文,因此它尚不具有导致其引发的orderSystem属性。

Using arrow functions or bind on the inner block might solve your issue. 在内部块上使用箭头功能或绑定可能会解决您的问题。 I tend to find when I have nested blocks like this using variables scoped to the outer block is a little cleaner. 我倾向于发现使用嵌套在外部块中的变量来嵌套这样的块时会更干净一些。

To follow up on the answer from @aaroncrows: 要跟踪@aaroncrows的答案,请执行以下操作:

By using lexical arrow functions (ES6 construct) the scope of your subsequent describe blocks can have access to the context of your outer describe block (the 'this'). 通过使用词汇箭头功能(ES6构造),后续描述块的范围可以访问外部描述块(“ this”)的上下文。 Here's your code with lexical arrow functions. 这是带有词汇箭头功能的代码。

    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  
                } 
            }])
        });
    });
});

If you are unfamiliar with arrow functions, I would highly recommend youtubing around for some deeper explanations. 如果您不熟悉箭头功能,强烈建议您在周围闲逛以获得更深入的解释。 Be aware that by using arrow functions, your context (or 'this') refers to the uppermost scope that it's inside of. 请注意,通过使用箭头函数,您的上下文(或“ this”)是指其内部的最高范围。 In this case, it's your describe block's anonymous function declaration (ie the first line of code). 在这种情况下,这是您describe块的匿名函数声明(即代码的第一行)。 However when accessing the 'this' in a lexical arrow function that is not nested within a function block, you may be accessing the global context (for example the Window object if your code is executing in the browser). 但是,当访问未嵌套在功能块内的词汇箭头函数中的“ this”时,您可能正在访问全局上下文(例如,如果代码在浏览器中执行,则为Window对象)。

Hope that helps! 希望有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM