The method being spied on by Sinon has not been called

Testing the code involves a simple process: it triggers a method based on a certain condition. If the condition is not met, another method from within the first one is triggered as an attribute.

app.js:

function test (fn, isActivated) {
  if (isActivated) {
    return fn('foo')
  }

  return fn.subFn('bar')
}

var fn = function (p) { return p }
fn.subFn = function (p) { return 'sub-' + p }

var resFn = test(fn, true)
var resSubFn = test(fn, false)

document.write(resFn) // displays 'foo' as expected
document.write(resSubFn) // displays 'bar' as expected

A spy has been placed on each method, but oddly enough, the spy on the fn method does not seem to work while the spy on the enclosed method subFn functions correctly. Here's the scenario:

app.test.js:

'use strict'

const chai = require('chai')
const sinon = require('sinon')
const trigger = require('../app').trigger

chai.should()

describe('test app', function () {
    before(function () {
      this.fn = function () {}
      this.fn.subFn = function () {}
      this.subFnSpy = sinon.spy(this.fn, 'subFn')
      this.fnSpy = sinon.spy(this.fn)
    })

    describe('isActivated is true', function () {
      before(function () {
        trigger(this.fn, true)
      })

      it('should invoke fn', function () {
        this.fnSpy.callCount.should.equal(1) // returns false because callCount = 0
      })
    })

    describe('isActivated is false', function () {
      before(function () {
        trigger(this.fn, false)
      })

      it('should invoke subFn', function () {
        this.subFnSpy.callCount.should.equal(1) // returns false because callCount = 0
      })
    })
  })

Since the spy on the fn function seems to be malfunctioning, I attempted using two separate methods. Unfortunately, both spies failed in this instance:

app.js:

exports.trigger = function (fn, subFn, isActivated) {
  if (isActivated) {
    return fn('fn')
  }

  return subFn('bar')
}

app.test.js

'use strict'

const chai = require('chai')
const sinon = require('sinon')
const trigger = require('../app').trigger

chai.should()

describe('test app', function () {
    before(function () {
      this.fn = function () {}
      this.subFn = function () {}
      this.fnSpy = sinon.spy(this.fn)
      this.subFnSpy = sinon.spy(this.subFn)
    })

    beforeEach(function () {
      this.fnSpy.reset()
      this.subFnSpy.reset()
    })

    describe('isActivated is true', function () {
      before(function () {
        trigger(this.fn, this.subFn, true)
      })

      it('should invoke fn if isActivated is true', function () {
        this.fnSpy.callCount.should.equal(1) // returns false
      })
    })

    describe('isActivated is false', function () {
      before(function () {
        trigger(this.fn, this.subFn, false)
      })

      it('should invoke subFn if isActivated is true', function () {
        this.subFnSpy.callCount.should.equal(1) // returns false
      })
    })
  })

Any suggestions on what might be going wrong here?

Answer №1

Although I couldn't find an exact solution, I came up with a workaround that is very close to one. It appears that the problem lies in how this.fn is handled within sinon.spy. Instead of the original code snippet:

this.fnSpy = sinon.spy(this.fn)
this.subFnSpy = sinon.spy(this.subFn)

We can make a slight adjustment and use the following approach instead:

this.fnSpy = sinon.spy(this, 'fn')
this.subFnSpy = sinon.spy(this.fn, 'subFn')

This change was facilitated by the fact that I am storing both fn and subFn within this.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way for various applications to access a common components folder in both React and React Native environments?

Currently, I am immersed in a project that involves creating two mobile apps. Our team opted to use react-native for development to leverage the benefits of cross-platform functionality. We have mapped out the structure of the project. Interestingly, in t ...

How can I update the color of a list item when it is clicked within a foreach loop using knockout js?

Currently, I am encountering an issue with changing the color when a user clicks on a list item using the latest version of knockout js. My goal is to change the color of a list item when it is clicked and maintain that color until another item is clicked, ...

PHP + MySQL + JavaScript for an Interactive Web Communication Platform

My goal is to develop a Web Chat system using PHP, MySQL, and JavaScript. Currently, I store messages in a MySQL database with an incremental ID (indexed), timestamp, sender, and message. To retrieve new messages, I use AJAX to query the database every 50 ...

When trying to apply styles using ng-style attribute with jQuery, Angular does not seem to

Check out this plunker showcasing the issue : http://plnkr.co/edit/1ceWH9o2WNVnUUoWE6Gm Take a look at the code : var app = angular.module('myApp', []); app.controller('myCtrl', function($scope) { console.log('yeah'); ...

Unusual conduct when employing basic directive for validation messages

Within my code, I have implemented the following directive: App.directive("validateMsgFor", function(){ return{ templateUrl : "view/templates/validateMsgFor.html", restrict: "E", scope: { field : "=" } ...

Angular has the ability to round numbers to the nearest integer using a pipe

How do we round a number to the nearest dollar or integer? For example, rounding 2729999.61 would result in 2730000. Is there a method in Angular template that can achieve this using the number pipe? Such as using | number or | number : '1.2-2' ...

Guide to showcasing a placeholder in MUI's Select component

How can I add the placeholder "Select a brand" to this select element? I've tried different options with no luck. Here is the code snippet I am working with: <FormControl fullWidth> <InputLabel id="demo-multiple-name-label" ...

Troubleshoot: KeystoneJS encountering duplicate key error when attempting to add a new item

I have searched for similar questions on this topic, but unfortunately, I haven't found a solution yet. In my Keystone Project, I am trying to set up a Gallery similar to a post. I want to have a list of galleries, each containing a selection of imag ...

Tips for effectively removing objects from a PixiJS application

I have embarked on a game development project using Pixi.js that involves items falling from the top of the canvas. The functionality I've implemented so far allows items to spawn and move down the canvas until they reach the end of the window, at whi ...

Oops! We encountered an internal server error while trying to resolve the import for "@vue/server-renderer"

Several months ago, I created a Vue 3 project using Vite and everything was running smoothly. However, today when I tried to make a small modification, an error occurred at runtime. All Vue files are showing the same error message: [vite] Internal server ...

Is it possible to create a "private" variable by utilizing prototype in JavaScript?

In my JavaScript code, I am trying to have a unique private variable for each "instance," but it seems that both instances end up using the same private variable. func = function(myName) { this.name = myName secret = myName func.prototype.tel ...

What is the best method for effectively eliminating duplicate objects with the same value from an array?

Let's say we have a collection of jqlite objects, and using the angular.equals function, we can determine if they are equal. How can we utilize this function to eliminate duplicate items from an array of jQlite objects? This is my attempted solution: ...

Can you explain the distinctions between using this['key'] and $data['key'] in the context of v-model?

Take a look at the snippet below, which includes three demos. The first two demos are functioning correctly (v-model is working fine). However, in the last demo, when you type something into the <input>, you will notice that this['test 1'] ...

Response coming from an ajax call in the form of a JSON

With the JSON string provided below: {cols:[{"id":"t","label":"Title","type":"string"},{"id":"l","label":"Avg ","type":"string"},{"id":"lb","label":"High","type":"string"},{"id":"lo","label":"Low","type":"string"}],rows:[{"c":[{"v":"Change navigation"},{"v ...

Is there a way to streamline this function call that appears to be redundantly repeating the same actions?

I have developed a function to search for blog posts, prioritizing titles over excerpts and excerpts over content when added to the containsQuery array. While the code seems to be working well, I have noticed that there is a lot of redundant code. How can ...

What is the best method for placing an element above all other elements on a page, regardless of the layout or styles being used?

I want to create a sticky button that remains fixed on the page regardless of its content and styles. The button should always be displayed on top of other elements, without relying on specific z-index values or pre-existing structures. This solution must ...

Discover the steps for integrating an object into a Ext.grid.Panel using Sencha Ext Js

Currently, I am utilizing Sencha Ext Js 4 and have integrated an Ext.grid.Panel into my project. I am interested in adding another element inside the header, such as a textbox. Is this achievable? {filterable: true, header: 'Unique' /*Here i w ...

`Why is it important to debug javascript code?`

I have some outdated JavaScript code that surprisingly still works in Internet Explorer from 2000-2002, but refuses to function properly in browsers like Firefox, Chrome, and Opera. I've come across various browser quirks where different browsers inte ...

What could be causing the error message about jQuery not being defined in this bookmarklet code, even though jQuery is already included

As I work on creating a bookmarklet, I encountered an issue with the code below. When I visit a page, it initially gives an error message saying "jQuery is not defined". However, upon clicking it again, the bookmarklet functions perfectly. var qrcodetog ...

Possible Inconsistencies with the LookAt Feature in Three.js

Attempting to use the lookAt function to make zombies move towards the character has been a challenge. The problem lies in the fact that they are not turning correctly but at odd angles. Here is the code snippet I tried: var pos = new THREE.Vector3(self ...