No output from jasmine-node on FilesizeWatcherSpec

2019-09-02 19:09发布

问题:

I'm new to Node.js and jasmine, and my JavaScript experience is old and rusty, so I'm a newbie there too. I finished Manuel Kiessling's book, The Node Beginner Book, and I am working my way through his second book, The Node Craftsman Book. I'm stuck on the FilesizeWatcher tutorial. I've been able to run earlier tests but this one is not working. There is a similar question on SO: No output from jasmine-node but the answer isn't working for me.

I'll post my code here and hopefully somebody can tell me what I'm doing wrong.

FilesizeWatcherSpec.js:

'use strict';

var FilesizeWatcher = require('./FilesizeWatcher');
var exec = require('child_process').exec;

describe('FilesizeWatcher', function() {
    var watcher;

    afterEach(function() {
        watcher.stop();
    });

    it('should fire a "grew" event when the file grew in size', function(done) {

        var path = './var/tmp/filesizewatcher.test';
        exec('rm -f ' + path + ' ; touch ' + path, function() {
            watcher = new FilesizeWatcher(path);

            watcher.on('grew', function(gain) {
                expect(gain).toBe(5);
                done();
            });

            exec('echo "test" > ' + path, function(){});

        });
    });

    it('should fire a "shrank" event when the file shrank in size', function(done) {

        var path = './var/tmp/filesizewatcher.test';
        exec('rm -f ' + path + ' ; echo "test" > ' + path, function() {
            watcher = new FilesizeWather(path);

            watcher.on('shrank', function(loss) {
                expect(loss).toBe(3);
                done();
            });

            exec('echo "a" > ' + path, function(){});

        });
    });

    it('should fire an "error" if path does not start', function(done) {

        var path = 'var/tmp/filesizewatcher.test';        
        watcher = new FilesizeWather(path); 

        watcher.on('error', function(err) {
            expect(err).toBe('Path does not start with a slash');
            done();
        });

    });

});

FilesizeWatcher.js:

'use strict';

var fs = require('fs');
var util = require('util');
var EventEmitter = require('events').EventEmitter;

var FilesizeWatcher = function (path) {
    var self = this;

    if (/^\//.test(path) === false) {
        process.nextTick(function() {
            self.emit('error', 'Path does not start with a slash');
        });
        return;
    }

    fs.stat(path, function (err, stats) {
        console.log('stats= ' + stats);
        self.lastfilesize = stats.size;
    });

    self.interval = setInterval(            
            function () {
                console.log('We are in function()');
                fs.stat(path, function (err, stats) {
                    if (stats.size > self.lastfilesize) {
                        self.emit('grew', stats.size - self.lastfilesize);
                        self.lastfilesize = stats.size;
                    }
                    if (stats.size < self.lastfilesize) {
                        self.emit('shrank', self.lastfilesize - stats.size);
                        self.lastfilesize = stats.size;
                    }
                }, 1000);
            });
};

util.inherits(FilesizeWatcher, EventEmitter);

FilesizeWatcher.prototype.stop = function () {
    clearInterval(this.interval);
};

module.exports = FilesizeWatcher;

Console output:

C:\Users\pdl\Projects\NodeCraftsman>jasmine-node ./FilesizeWatcherSpec.js

C:\Users\pdl\Projects\NodeCraftsman>

Other tests run fine:

C:\Users\pdl\Projects\NodeCraftsmanTestDrivenDevelopment>jasmine-node spec\greetSpec.js
..

Finished in 0.006 seconds
2 tests, 2 assertions, 0 failures, 0 skipped


C:\Users\pdl\Projects\NodeCraftsmanTestDrivenDevelopment>

I added --captureExceptions to see if I could get any information and I got the TypeError: self.callbacks.error is not a function.

My first problem was as Eppilo suggested below, that I needed to use process.nextTick on self.callbacks'error'. Mixing async code with sync code causes the error event to be fired before the error handler is registered. So I made the changes and am now using the EventEmitter but I'm still getting the following errors:

If I include the "." in the path: var path = './var/tmp/filesizewatcher.test'; then the file gets written. Otherwise, it does not.

If the file does NOT get written, stats= undefined and I receive this error:

TypeError: Cannot read property 'size' of undefined
    at C:\Users\pdl\Projects\NodeCraftsman\FilesizeWatcher.js:19:34
    at FSReqWrap.oncomplete (fs.js:82:15)

If the file DOES get written, then I receive this error:

Error: Uncaught, unspecified "error" event. (Path does not start with a slash)
    at emit (events.js:144:17)
    at C:\Users\pdl\Projects\NodeCraftsman\FilesizeWatcher.js:12:18
    at nextTickCallbackWith0Args (node.js:419:9)
    at process._tickCallback (node.js:348:13)

Of course, it's not supposed to start with a slash. That is the test. But when I remove the --captureExceptions from the command, I still get no output.

回答1:

First of all try and run Jasmine on verbose mode and capture exceptions:

jasmine-node ./FilesizeWatcherSpec.js --verbose --captureExceptions

Link: https://github.com/mhevery/jasmine-node/wiki/Command-Line-Usage

Also try to make the error checking asynchronous:

if (/^\//.test(path) === false) {
    process.nextTick(function() {
        self.callbacks['error']('Path does not start with a slash');
    });
    return;
}


回答2:

Newbie as well, with not enough reputation to comment.

I got the same no output on my Mac too, and was able to get the test to work with this.

There is an error in FilesizeWatcher.js.

Currently:

self.interval = setInterval(
    function (){ 
       ...          
       fs.stat(path, function (err, stats) {
          ...
    }, 1000); 
});

It should instead be:

self.interval = setInterval(
    function (){ 
       ...          
       fs.stat(path, function (err, stats) {
          ...
    }); 
},1000);

Just sharing my findings, cheers.