Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Squire is breaking other tests

I'm using Karma, Jasmine, Jasmine.Async, Sinon and Chai.

The good news...this test works correctly. The dependency is mocked, spies get called, and intentionally breaking the test subject results in failed tests.

define(['chai', 'squire'], function (chai, Squire) {

    var should = chai.should(),
        async = new AsyncSpec(this),
        subject, injector = new Squire();

    describe('EventsView', function () {

        describe('when an event is clicked', function () {
            var mockModel, stub;

            async.beforeEach(function (done) {
                setFixtures('<div id="screen"></div>');

                mockModel = {
                    toJSON: function () {
                        return {
                            dimensions: "hu1 vu2",
                            events: [{
                                date: "8/29/2013",
                                id: "8923",
                                title: "Fancy Show",
                                venue: "Lovely venue",
                            }, {
                                date: "8/29/2013",
                                id: "9034",
                                title: "Exciting Game",
                                venue: "Lovely stadium"
                            }],
                            id: 3566,
                            kind: "events",
                            title: "Top events this week"
                        };
                    },
                    fetch: function () {}
                };
                stub = sinon.stub();
                injector.mock('tiles/events-tile/events-detail-model', Squire.Helpers.constructs({
                    fetch: stub
                }));
                injector.require(["tiles/events-tile/events-view"], function (ev) {
                    subject = new ev(mockModel);
                    done();
                });
            });

            async.afterEach(function (done) {
                injector.clean();
                injector.remove();
                done();
            });


            async.it('should attempt to fetch the event details', function (done) {
                $('#screen').html(subject.$el);
                $('.event').first().click();
                stub.called.should.be.true;
                done();
            });
        });
    });
});

The bad news...a shed load of other tests that were previously fine are now failing for weird reasons. For example: Error: Backbone.history has already been started and TypeError: 'undefined' is not an object (evaluating 'Backbone.Validation.mixin')

If I comment out the snippet

injector.require(["tiles/events-tile/events-view"], function (ev) {
  subject = new ev(mockModel);
    done();
});

Then the other tests work again. I've had stuff like this happen before and it has usually been down to a sinon mock not getting restored. The injector.clean() call doesn't seem to be providing the magic bullet I was hoping for.

like image 524
Dom Barker Avatar asked Sep 15 '13 10:09

Dom Barker


2 Answers

In my experience, Squire causes way more headaches than it solves. Are you using any jQuery plugins? I've found that they don't play well with squire and can cause subsequent tests to fail. If that's the case, check out this blog about how to deal with that.

My recommendation, however, is to ditch Squire entirely. Using sinon and creating your own utilities to mock exactly what you need should not only make your asynchronous tests synchronous again (where the code under test is synchronous), but it will also encourage the creation of more testable code. It should also help you understand your code and libraries at a deeper level-- stubbing Backbone.history to perform routing actions without actually triggering routes is a great exercise and a fantastic utility to add to your test library.

like image 156
maher.cs Avatar answered Oct 13 '22 01:10

maher.cs


The problem is with non AMD modules. If I remember correctly when Squire creates a new context it will create a new instance of the non AMD module in the global namespace. The result is that your code and test will reference a different object. I think I managed to solve this problem by doing:

var injector = new Squire();
injector.mock("backbone", function() {
  return Backbone;
});

Squire should handle non AMD modules better.

like image 25
chchrist Avatar answered Oct 12 '22 23:10

chchrist