在sinon中“从头开始”创建一个假的object.method()?

时间:2015-05-12 18:03:51

标签: javascript node.js mocha sinon chai

TL;博士

如何在sinon中“从头开始”创建object.method()?

上下文

例如,我有一个Parser类系列,每个类实现一个#parse(text)方法并返回一个ParseTree对象或返回null

我正在进行单元测试,我测试Parser个对象本身(它们在别处测试)但我需要一个响应#parse()的可测试对象。我可以实例化并存根一个真正的Parser,但这会将不必要的代码拖入测试的这一部分。

问题

我很确定使用sinon的spy(),stub()和/或mock()api很容易,所以:我如何创建一个可测试的对象:

  • 响应parse()方法
  • 验证它是否被调用
  • 返回我指定的任意对象?

我尝试了什么

以下设计示例在调用sinon.stub()时失败,因为sinon.spy()对象无法使用parse方法存根。 (此示例还应验证fake_parser.parse()是否使用test_text调用了var test_text = 'any text' var fake_parse_tree = sinon.spy() var fake_parser = sinon.stub(sinon.spy(), 'parse').returns(fake_parse_tree) expect(fake_parser.parse(test_text)).to.equal(fake_parse_tree) ,但它没有调用:

(function($){
function floatLabel(inputType){
        $(inputType).each(function(){
            var $this = $(this);
            var text_value = $(this).val();

            // on focus add class "active" to label
            $this.focus(function(){
                $this.next().addClass("active");
            });

            // on blur check field and remove class if needed
            $this.blur(function(){
                if($this.val() === '' || $this.val() === 'blank'){
                    $this.next().removeClass();
                    }
            });

            // Check input values on postback and add class "active" if value exists
            if(text_value!==''){
                $this.next().addClass("active");
                }
            });
    // Automatically remove floatLabel class from select input on load
    //$( "select" ).next().removeClass();
}
// Add a class of "floatLabel" to the input field
floatLabel(".floatLabel");
});

2 个答案:

答案 0 :(得分:4)

创建一个虚拟parse()对象并存根它的var Parser = { parse: function() { } }; var parseStub = sinon.stub(Parser, 'parse'); parseStub.returns(fake_parse_tree); // execute code that invokes the parser parseStub.callCount.should.equal(1); parseStub.alwaysCalledWithExactly(test_text).should.be.true(); 方法。详细信息将取决于您创建解析器的方式,但类似于:

Set body = New NotesRichTextItem(maildoc,"Body")
Call body.AppendDocLink(doc, "Click me") 

答案 1 :(得分:2)

@Stephen Thomas gave the right answer here。为了将来参考,这是我最终做的。 'aha'是sinon.stub(object, 'method')返回存根方法,而不是对象。

因为这是javascript(并且方法是第一类对象),所以返回该方法非常有意义:

var test_text = 'any text';
var parse_tree = sinon.spy(); // could be any object
var proxy_parser = { parseText: function() { } };
var stubbed_method = sinon.stub(proxy_parser, 'parseText').returns(parse_tree)

// App specific tests not shown here:
// ...pass proxy_parser to a function that calls proxy_parser.parseText()
// ...verify that the function returned the parse_tree

expect(stubbed_method.callCount).to.equal(1)
expect(stubbed_method.alwaysCalledWithExactly(test_text)).to.be.true