10

我在 Jasmine 中进行间谍活动时遇到了一些麻烦

我想检查是否使用 jasmine spy 和 jasmine jquery 在滑块上单击了链接。

这是一个简化版本:

我有一些链接作为 html 固定文件的一部分。

<a href="#" class="someLink">Link 1</a>
<a href="#" class="someLink">Link 2</a>

滑块:

var Slider = function(links){
    this.sliderLinks = $(links);
    this.bindEvents();
}

Slider.prototype.bindEvents = function(){
    this.sliderLinks.on('click', this.handleClick);
}

Slider.prototype.handleClick = function(e){
    console.log('i have been clicked')
}

规格文件:

describe('Slider', function(){
    var slider;

    beforeEach(function(){
        loadFixtures('slider.html');

        slider = new Slider('.someLink');

    });

    it('should handle link click', function(){
        spyOn(slider, 'handleClick');
        $(slider.sliderLinks[0]).trigger('click');
        expect(slider.handleClick).toHaveBeenCalled();
    });

});

测试失败。但是“我已被点击”已记录到控制台,因此正在调用该方法。

如果我这样做,则测试通过:

it('should handle link click', function(){
        spyon(slider, 'handleClick');
        slider.handleClick();
        expect(slider.handleClick).toHaveBeenCalled();
    });

所以我的问题本质上是:

  1. 我是否以错误的方式测试这种类型的东西?
  2. 为什么间谍没有记录该方法已被调用的事实?
4

1 回答 1

25

我刚刚验证了评论中概述的解决方案。你describe应该是:

describe('Slider', function () {

    var slider;

    beforeEach(function () {
        loadFixtures('slider.html');
        spyOn(Slider.prototype, 'handleClick');
        slider = new Slider('.someLink');
    });

    it('should handle link click', function (){
        $(slider.sliderLinks[0]).trigger('click');
        expect(slider.handleClick).toHaveBeenCalled();
    });

});

关键是你必须在原型函数handleClick和创建之前Slider监视。

原因是 JasminespyOn在您提供的代码中真正做了什么:

spyOn(slider, 'handleClick');

handleClick直接在slider实例上创建滑块属性(包含间谍对象)。slider.hasOwnProperty('handleClick')在这种情况下返回true,你知道......

但是,handleClick您的点击事件仍然绑定到原型属性。这意味着刚刚触发的点击事件由原型handleClick函数处理,而滑块对象自己的属性handleClick(您的间谍)保持不变。

所以答案是间谍没有记录该方法已被调用的事实,因为它从未被调用过:-)

于 2013-07-29T09:42:28.717 回答