Reputation: 1717
I'm having trouble with testing my file access with jasmine. I am writing a simple watcher that registers a callback with require('fs').watch
and emits an event containing the name of the file, nothing fancy here.
However when I try to write tests that mock the fs
module I have several problems.
Here is my Watcher class (CoffeeScript ahead)
class Watcher extends EventEmitter
constructor: ->
@files = []
watch: (filename) ->
if !path.existsSync filename
throw "File does not exist."
@files.push(filename)
fs.watchFile filename, (current, previous) ->
this.emit('file_changed')
And here are my tests :
it 'should check if the file exists', ->
spyOn(path, 'existsSync').andReturn(true)
watcher.watch 'existing_file.js'
expect(path.existsSync).toHaveBeenCalledWith 'existing_file.js'
This one works well and passes without any problem but this one fails completely, I am not sure if I am passing correctly the arguments.
it 'should throw an exception if file doesn\'t exists', ->
spyOn(path, 'existsSync').andReturn(false)
expect(watcher.watch, 'undefined_file.js').toThrow()
expect(path.existsSync).toHaveBeenCalledWith 'undefined_file.js'
And the last one gives me and odd '([Object] does not have a method emit)' which is wrong.
it 'should emit an event when a file changes', ->
spyOn(fs, 'watchFile').andCallFake (file, callback) ->
setTimeout( ->
callback {mtime: 10}, {mtime: 5}
, 100)
spyOn(path, 'existsSync').andReturn(true)
watcher.watch 'existing_file.js'
waits 500
expect(watcher.emit).toHaveBeenCalledWith('file_changed')
For the second problem I just wrapped my function call in a closure and it worked but I really need to understand why when running my tests, the this
context is totally messed up.
Upvotes: 3
Views: 3477
Reputation: 146114
See this question
I think you need to do:
expect(-> watcher.watch 'undefined_file.js').toThrow 'File does not exist.'
Which defines an anonymous function that the expect matcher can invoke during the actual test run, as opposed to during test definition time.
For your second issue, you can only call toHaveBeenCalled
on a jasmine spy object, not any arbitrary function. You can just wrap the function with doing
spyOn(watcher, 'emit').andCallThrough()
See the jasmine API docs on Spy.andCallThrough()
Upvotes: 2