2014-04-30 56 views
-1

我想寫一個更新的手錶模塊,使用fs.watch方法,而不是watchFile方法。摩卡測試失敗,但實施工程

到目前爲止,它的工作很好,但只有當我在摩卡之外運行它。我無法弄清楚爲什麼我的單元測試會發脾氣,也許這裏有人可以?

這裏是我的類代碼:

/** 
* requirements 
*/ 
var fs, path, events; 
fs = require('fs'); 
path = require('path'); 
events = require('events'); 


/** 
* private 
*/ 
var Monitor = function(directory, options) { 
    this.directory = directory; 
    this.options = options || {}; 
    (this.options.lazy && this.empty()) || this.walk(this.directory); 
    this.watch(this.directory); 
}; 
Monitor.prototype = new events.EventEmitter(); 
Monitor.prototype.watch = function(directory, stats) { 
    var stats = stats || {}; 
    if (!this.directories[directory]) { 
     var w = fs.watch(directory, this.options, this.justlookatit.bind(this)); 
    } 
    this.directories[directory] = { 'stats': stats, 'w': w }; 
}; 
Monitor.prototype.directories = function() { 
    if (!Object.keys(this.directories).length) { 
     this.walk(this.directory); 
    } 
    return this.directories; 
}; 
Monitor.prototype.files = function() { 
    if (!Object.keys(this.files).length) { 
     this.walk(this.directory); 
    } 
    return this.files; 
}; 
Monitor.prototype.unwatch = function() { 
    if (!Object.keys(this.directories).length) { 
     for (var dir in this.directories) { 
      dir.w.close(); 
     } 
    } 
}; 
Monitor.prototype.empty = function() { 
    this.unwatch(); 
    this.files = {}; 
    this.directories = {}; 
}; 
Monitor.prototype.walk = function(directory) { 
    var monitor = this; 
    this.empty(); 
    fs.readdir(directory, function(err, files) { 
     if (err) return; 
     for (var file in files) { 
      var fullname = path.resolve(files[file]); 
      if (!monitor.options.filter || monitor.options.filter(fullname)) { 
       fs.stat(fullname, function(err, stats) { 
        if (err) return; 
        if (stats.isDirectory()) { 
         monitor.walk(fullname); 
         monitor.watch(fullname, stats); 
        } else { 
         monitor.files[fullname] = stats; 
        } 
       }); 
      } 
     } 
    }); 
}; 
Monitor.prototype.justlookatit = function(action, file) { 
    var monitor = this; 
    var fullname = path.resolve(file); 
    if (this.options.filter && !this.options.filer(fullname)) return; 
    fs.exists(fullname, function(exists) { 
     if (exists) { 
      fs.stat(fullname, function(err, stats) { 
       if (stats.isDirectory()) { 
        monitor.watch(fullname, stats); 
       } else { 
        if (monitor.files[fullname]) { 
         if (stats.mtime.getTime() > monitor.files[fullname].mtime.getTime()) { 
          monitor.emit('modified', fullname, stats); 
         } 
        } else { 
         monitor.emit('added', fullname, stats); 
        } 
        monitor.files[fullname] = stats; 
       } 
      }); 
     } else { 
      if (monitor.files[fullname]) { 
       delete monitor.files[fullname]; 
       monitor.emit('deleted', fullname); 
      } else if (monitor.directories[fullname]) { 
       monitor.directories[fullname].w.close(); 
       delete monitor.directories[fullname]; 
      } 
     } 
    }); 
}; 


/** 
* exports 
*/ 
exports.start = function(directory, options) { 
    return new Monitor(directory, options); 
}; 

這是我的工作外部測試代碼:

var watch = require("./watch.js"); 
var fs = require('fs'); 
monitor = watch.start(__dirname); 

monitor.on('added', function(file, stats) { 
    console.log("Caught Added: " + file); 
}); 

monitor.on('modified', function(file, stats) { 
    console.log("Caught Modified: " + file); 
}); 

monitor.on('deleted', function(file) { 
    console.log("Caught deleted: " + file); 
}); 

// try creating a file immediately 
fs.openSync('v.md', 'w'); 

第一個測試文件運行完全正常,我都試過openSyncopen。最後,這裏是一個版本相同的測試代碼,包裹在摩卡單元測試,已超時:

/** 
* requirements 
*/ 
var watch, Q, fs, path, mocha, chai, assert; 
watch = require('../lib/watch.js'); 
Q = require('q'); 
fs = require('fs'); 
path = require('path'); 
mocha = require('mocha'); 
chai = require('chai'); 
assert = chai.assert; 

/** 
* variables 
*/ 
var watch_directory = path.join(__dirname, './watch'); 


/** 
* tests 
*/ 
describe('test watch', function() { 
    it('should create a monitor and run callbacks after fs changes', function(done) { 

     // I had planned to implement promises that chained the three callbacks 
     // but couldn't get one of them working in general 
     var added = function(file, stats) { 
      console.log("added"); 
      done(); 
     }; 
     var modified = function(file, stats) { 
      console.log("modified"); 
     }; 
     var deleted = function(file, stats) { 
      console.log("deleted"); 
     }; 

     // create our service 
     var monitor = watch.start(watch_directory); 

     // assert it is defined 
     assert.isDefined(monitor); 

     // establish a listener 
     monitor.on('added', added); 
     monitor.on('modified', modified); 
     monitor.on('deleted', deleted); 

     // here is a file name using the current date to prevent duplication during tests 
     var file = path.join(watch_directory, (new Date()).getTime() + '.md'); 

     // let's create the file, then delete it 
     fs.open(file, 'w+', function(err, fileDescriptor) { 

      // this prints before console output from the watch.js's `justlookatit` method 
      console.log(err); 
      console.log("writing to file"); 

      // we probably don't want to try closing the fileDescriptor if the open failed 
      if (err) return; 

      // close the file descriptor 
      fs.close(fileDescriptor, function() { 
       // delete the file we just created 
       // fs.unlink(file, function() { /* not a big deal */ }); 
      }); 
     }); 

     // modify a known-existing test file 
     fs.open('test.md', 'w+', function() {/* we don't care about this */}); 

    }) 
}); 

console.log(fullname)檢查了手表的代碼justlookatit方法裏面,它吐出來的是正確的文件名稱,與單元測試生成的名稱匹配。

然而,當我運行fs.exists時,它接着返回false。由於我不理解它,這意味着文件系統在文件存在之前通知我文件存在,這實際上沒有意義。所以我試圖通過將我的fs.exists方法包裝在setTimeout中來增加額外的延遲,但這並沒有改變結果。我也嘗試過使用openSync和existsSync,並沒有什麼區別。

我很難過,有沒有人有任何想法爲什麼摩卡代碼不工作?

回答

-1

您在測試結束時錯過了回調return(done);。除非你給這個回調打電話,否則摩卡每次都會超時。

+0

done正在從'added'回調中被調用,當監視器發出添加了一個新文件時,它應該由監視器執行,這是'fs.open'進程打算處理的內容。理想情況下,我會創建一個承諾鏈,一旦三者全部滿足,就會導致完成方法。 – CDeLorme

0

所以,解決的辦法是去散步。我回來了,再次查看了代碼,並找出了摩卡問題的原因,並發現了許多其他錯誤。

問題在於缺乏上下文。 justlookatit方法沒有上下文,並且在test.js方案中它正在觀察當前目錄,而mocha測試正在觀察子目錄。

path.resolve僅接收文件名,而不是目錄,因此將其與默認(可執行文件)目錄合併,因此摩卡的test.jswatch_test.js的級別。它繼續無法找到摩卡測試用例中的任何文件,因爲它們都低於可執行文件的一個級別。

我不會詳細討論所有其他的錯誤,但是當我想要將它推向聯機時,我可能會回來併發布存儲庫鏈接。

相關問題