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?
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:
If unnamed, wrap each chunk of functionality in a self-executing, named method
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.
Once you're green, start refactoring into small, well-named, well-organized methods / namespaces
Write isolated tests to characterize those units
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.
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
© 2022 - 2024 — McMap. All rights reserved.
function(window, document, undefined){...}(window, document)
where...
is your code. Simply concatenating the code will suffice. – Tarlatan