DEV Community

Jan Küster
Jan Küster

Posted on

Keeping Javascript test naming updated after refactoring

Some days ago I ran into a problem. I refactored (simply renamed) some Functions and faced the situation, that I also had to update all the names in my tests, too... manually!

This is because I did not assigned the Functions a proper name, when I created them as a property of something else:

export const Utils = {}

Utils.isDefined = function (obj) {
  return typeof obj !== 'undefined' && obj !== null
}

// ...
Enter fullscreen mode Exit fullscreen mode

In the tests I then wrote the function name by hand:

import { Utils } from '../Utils.js'

describe ('Utils', function () {
  describe ('isDefined', function () {
    // ...
  })
})
Enter fullscreen mode Exit fullscreen mode

Now later I realized, that the name isDefined is somewhat wrong picked and I refactored it to exists:

Utils.exists = function (obj) { 
  return typeof obj !== 'undefined' && obj !== null
}
Enter fullscreen mode Exit fullscreen mode

Well, my tests were not covered by the update and still were outputting the old isDefined:

Utils
  isDefined
    ✓ ...
Enter fullscreen mode Exit fullscreen mode

I was thinking "how could I make my test automatically reflect my Function's namespaces?" and luckily (since ECMA2015) there is a nice way to always get a Function's name, using the name property:

import { Utils } from '../Utils.js'

describe ('Utils', function () {
  describe (Utils.exists.name, function () {
    // ...
  })
})
Enter fullscreen mode Exit fullscreen mode

This will always be the Function's name, because it references to it and is thus covered by the refactoring. Keep in mind however, that in the current state of this code there will be nothing returned as name. This is because the Function simply has no name, yet. To do so we need to declare not only the property but also the Function name:

Utils.exists = function exists (obj) { 
  return typeof obj !== 'undefined' && obj !== null
}
Enter fullscreen mode Exit fullscreen mode

and the tests are then automatically reflecting the naming:

Utils
  exists
    ✓ ...
Enter fullscreen mode Exit fullscreen mode

Simple tweak with a great reduction in follow-up work here. For those of you, who think this would then require to double rename (property and Function name) then I encourage you to try out with your IDE: usually you should just have to refactor-rename one of them to trigger the refactoring of both.

Note, that in order to make this work with arrow functions, you need to declare them as variables:

const exists = (obj) => typeof obj !== 'undefined' && obj !== null
Utils.exists = exists
Enter fullscreen mode Exit fullscreen mode

Top comments (0)