Stub out a jQuery selector call?

后端 未结 3 1856
别跟我提以往
别跟我提以往 2020-12-15 04:36

I\'m trying to get better at unit testing my JavaScript. I have the following code:

var categoryVal = $(\'#category\').val();
if (categoryVal === \'\') { 
           


        
3条回答
  •  再見小時候
    2020-12-15 05:20

    The problem here is that $() is a function that returns an object with the method val(). So you have to stub $() to return a stubbed object having the method val.

    $ = sinon.stub();
    $.withArgs('#category').returns(sinon.stub({val: function(){}}));
    

    But the main mistake here is to let the code you want to test call the function $() to create new instances. Why? Its best practice to create no new instances in your class, but to pass them into the constructor. Let's say you have function that will get a value out of an input, double it, and write it back to another:

    function doubleIt(){
        $('#el2').val(('#el1').val() *2);
    }
    

    In this case you create 2 new objects by calling $(). Now you have to stub $() to return a mock and a stub. Using the next example you can avoid this:

    function doubleIt(el1, el2){
        el2.val(el1.val() *2);
    }
    

    While, in the first case you have to stub $ to return a stub, in the second case you can easily pass a stub and a spy into your function.

    So the sinon test for the second one would look like this:

    var el1 =  sinon.stub({val: function(){}});
        el1.returns(2);
    
    var el2 = sinon.spy({val: function(){}}, 'val')
    
    doubleIt(el1, el2)
    
    assert(el2.withArgs(4).calledOnce)
    

    So, as you have no dom elements here, you can simply test your application logic with no need to create the same dom as in your app.

提交回复
热议问题