Can JavaScript be "unit testable" if wrapped in self-executing anonymous function
Asked Answered
R

2

11

As I see many times, a self-executing anonymous function is used to contain entire libraries. How can these libraries be tested, if e.g. QUnit cannot access anything inside the anonymous function wrapper?

Richly answered 17/8, 2011 at 12:17 Comment(1)
You can work on the code (and test it) and use a "build" script to wrap it into the wrapper. IE function(window, document, undefined){...}(window, document) where ... is your code. Simply concatenating the code will suffice.Tarlatan
N
6

I agree that you don't want to perform Backdoor Manipulation by finding sneaky ways to discretely test private methods.

However, as you pointed out, leagues upon leagues of web applications were written as one gigantic self-executing ball of mud that lacks any naming or public API. That's a completely different problem that one is unlikely to encounter in many other tech stacks.

One of the huge values of TDD'ing JavaScript for the web is that it forces you to write JavaScript that's usable by at least two parties: your web app + your unit test.

I've played this legacy rescue game a few times with Jasmine:

  1. If unnamed, wrap each chunk of functionality in a self-executing, named method

  2. Characterize those methods with functional Jasmine specs. I love Jasmine for lots of reasons, but it really has qunit beat at legacy rescue because of it's ability to nest example groups. For instance, whenever the code I'm characterizing has an anonymous function, it's usually possible to use a nested example group to discretely characterize the behavior of that nested function by nabbing it with a spy and invoking it under different contexts.

  3. Once you're green, start refactoring into small, well-named, well-organized methods / namespaces

  4. Write isolated tests to characterize those units

  5. Eat a sandwich and ponder whether those functional tests are still valuable (if you don't have any full-stack tests they probably are; if you already have good full-stack tests it's probably too redundant to warrant maintaining them). Because I usually drive development with Cucumber/Capybara, I don't see much value in writing integrated tests with Jasmine.

Nanci answered 19/8, 2011 at 2:15 Comment(0)
D
2

You just do all your tests on that "public" function, see for example the official jQuery core test suite

Fragment:

// Basic constructor's behavior

equals( jQuery().length, 0, "jQuery() === jQuery([])" );
equals( jQuery(undefined).length, 0, "jQuery(undefined) === jQuery([])" );
equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" );
equals( jQuery("").length, 0, "jQuery('') === jQuery([])" );
equals( jQuery("#").length, 0, "jQuery('#') === jQuery([])" );

You don't need to access private functions to test public behaviour

Daff answered 17/8, 2011 at 14:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.