Testing Coffeescript with Jasmine and Rails 3.1



假设我在Coffeescrapt:中有一个类

class MyGame
   constructor: () ->
      @me = new Player
      @opponents = [new Player, new Player]

哪个想在Jasmine中测试:

describe "MyGame", ->
   beforeEach ->
     window.game = new MyGame
   it "should have two players", ->
      expect(window.game.opponents.length).toEqual 2

但是我得到了错误TypeError: Result of expression 'window.game.opponents' [undefined] is not an object.

window.game的方法对我来说也很尴尬。如果我试图将其定义为@game = new MyGame,我会得到错误ReferenceError: Can't find variable: MyGame,但我想这与Coffeescapet的包装方式有关?

更新:这个问题看起来更像是上面描述的一个参考问题。我用guard-jasmine运行,它看起来像

guard 'jasmine', :all_on_start => false, :all_after_pass => false do
  watch(%r{app/assets/javascripts/(.+).(js.coffee|js)}) { |m| "spec/javascripts/#{m[1]}_spec.#{m[2]}" }
  watch(%r{spec/javascripts/(.+)_spec.(js.coffee|js)})  { |m| "spec/javascripts/#{m[1]}_spec.#{m[2]}" }
  watch(%r{spec/javascripts/spec.(js.coffee|js)})       { "spec/javascripts" }
end

我的jasmine.yml文件有:

src_files:
    - "app/assets/**/*.js"
    - "app/assets/**/*.coffee"
spec_files: 
    - '**/*[sS]pec.js.coffee' 
asset_pipeline_paths: 
    - app/assets 
    - spec/javascripts

我得到了一个ReferenceError: Can't find variable: MyGame,所以我认为它要么是Rails3.1资产管道的东西,要么是Coffeescapet包装对象的方式。

尝试使用@运算符定义coffeescript类,如下所示:

class @MyGame
   constructor: () ->
      @me = new Player
      @opponents = [new Player, new Player]

这将允许您从任何地方访问类,例如从您的jasmine测试,并且您还可以避免将测试变量附加到窗口:

describe "MyGame", ->
   beforeEach ->
     @game = new MyGame
   it "should have two players", ->
      expect(@game.opponents.length).toEqual 2

原因是coffeescript通过将所有内容封装在闭包中来避免引入全局变量。不幸的是,这对于面向对象的代码来说可能是不可取的。使用@操作符将类定义附加到全局this,即window,从而允许您根据需要实例化类。你现在可能在你的全局空间,你的类中有一些全局变量,但对我来说,这是一个不错的权衡。希望这能有所帮助!

我不愿意接受在所有主干类前面使用@符号来修改代码的名称空间,所以我仔细研究了一些,对我有效的解决方案是要求在我的spec/javascripts/spec.js.coffee文件中使用应用程序文件

#= require application
window.game = () -> new MyGame

这将为window.game分配一个返回新MyGame的函数。你不是直接想要新实例吗?

window.game = new MyGame

window.game方法对我来说也很尴尬。

这个怎么样

describe "MyGame", ->
   game = null
   beforeEach ->
     game = new MyGame
   it "should have two players", ->
      expect(game.opponents.length).toEqual 2

例如,我通过将每个类定义为class window.MyGame来解决了这个问题。在规范文件中,我将#= require my_file_name放在顶部。

此外,我将jasminerice.js.coffeejquery.js都放置在app/assets/javascripts中。这可能不是最好的解决方案,因为我认为它们应该放在spec/javascripts/helpers中,因为我的spec.js.coffee的内容是#=require_tree ./

我知道这不是很优雅,但它可能会帮助其他处于同样情况的人@Thilo感谢您的投入。

最新更新