2015-07-12 25 views
16

我有一个函数茉莉花 - 如何spyOn实例方法

var data = {}; 
var myFunc = function() { 
    data.stuff = new ClassName().doA().doB().doC(); 
}; 

我想测试doAdoBdoC都调用。

我试图刺探实例方法这样

beforeEach(function() { 
    spyOn(ClassName, 'doA'); 
}; 
it('should call doA', function() { 
    myFunc(); 
    expect(ClassName.doA)toHaveBeenCalled(); 
}); 

但只是给了我一个“DOA()方法不存在”的错误。

任何想法?

+0

之间有一个主要区别'ClassName.doA'和'ClassName.doA()'。 – bardzusny

回答

24

您错误的地方在于您了解如何在静态上下文中引用JavaScript中的方法。你的代码实际上在做的是在ClassName.doA(也就是ClassName构造函数的属性doA,这不是你想要的)附加功能。

如果您想要检测何时在任何地方ClassName的任何实例上调用该方法,您需要监视原型。

beforeEach(function() { 
    spyOn(ClassName.prototype, 'doA'); 
}); 
it('should call doA', function() { 
    myFunc(); 
    expect(ClassName.prototype.doA).toHaveBeenCalled(); 
}); 

当然,这是假设doA住在原型链中。如果它是一个自己的属性,那么没有能够引用myFunc中的匿名对象的方法就没有任何技术可用。如果您有权访问myFunc中的ClassName实例,那么这将是理想的,因为您可以直接对spyOn进行操作。

P.S.你应该真的把“茉莉花”的标题。

+0

我们正面临类似的挑战,其中'ClassName.prototype.doA'方法会触发,但实例字段不会在'ClassName'的实例中实例化。实例字段在构造函数中填充,但不幸的是,当我们正在监视其中一个实例方法时,它们都是未定义的。 –

+0

哇,很好的答案。我一直使用https://github.com/mfncooper/mockery模拟需要模块缓存中的整个构造函数。它不仅更加冗长,而且有时会导致测试难以发现调试问题。这是一个很容易理解的很好的解决方案。茉莉花真的应该在他们的文档中包含这个例子。 – Eric

5

让我们做一些代码重构,因为我们希望实现构造注塑模式詹姆斯岸提到:

依赖注入意味着放弃一个对象自身的实例变量。真。而已。

var data = {}; 
var stuff = new ClassName() 

var myFunc = function(stuff) { // move step of creation new object outside 
    data.stuff = stuff.doA().doB().doC(); 
}; 

而且时间一些测试

function ClassName() { 
 
} 
 

 
var data = {}; 
 
var stuff = new ClassName() 
 

 
var myFunc = function(stuff) { 
 
    data.stuff = stuff.doA().doB().doC(); 
 
}; 
 

 

 
describe('stub for ClassName implementation', function() { 
 
    var stubStuff = { 
 
    doA: function() { 
 
     return stubStuff 
 
    }, 
 
    doB: function() { 
 
     return stubStuff 
 
    }, 
 
    doC: function() { 
 
     return stubStuff 
 
    } 
 
    } 
 

 
    beforeEach(function() { 
 
    spyOn(stubStuff, 'doA').and.callThrough(); 
 
    }); 
 

 
    it('calls "doA" on "myFunc" exection', function() { 
 
    myFunc(stubStuff); 
 
    expect(stubStuff.doA).toHaveBeenCalled(); 
 
    }); 
 
});
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" /> 
 
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>