使用javascript / coffeescript进行依赖注入以帮助测试

我正在我的网络应用程序中使用Jasmine进行一些测试.我正在使用Coffeescript来编写我的模型,服务和视图模型.

class MyViewModel
  constructor: ( @options ) ->
    @alert = new Alert
      elementId: 'my-alert-element-id'

    @service = new MyService
      alertId: @alert.elementId

现在我用茉莉花写一个测试

describe 'MyViewModel', ->
  sut = null

  beforeEach ->
    sut = new MyViewModel()

  afterEach ->
    sut = null

  describe 'constructor()', ->
    it 'creates a new instance of the ViewModel', ->
      expect( sut ).not.toBeNull()

所以这里的问题是我在viewModel中依赖于警报和服务.这使得测试很难编写和维护.

在Javascript中是否存在用于依赖注入的库.我使用了几个.net库,如castle windsor和ninject.

或者我应该采用某种类型的模式.我应该说我正在使用knockout,当我在实际应用程序中使用viewmodel时,它看起来像这样.

<script type="text/javascript">

  $(function () {
    var viewModel = new MyViewModel();
    ko.applyBindings(viewModel);
  });

</script>

而不是我创建自己的对象,我会问我注入的MyViewModel实例的注入框架.

我正在寻找有关采用什么模式或库的建议,以使我的测试更容易,并帮助我的javascript类彼此解耦.

Libs我发现:

> Wire – 只有ECMA 5和我需要支持旧浏览器
> Dijon – 看起来不错,但我还没有尝试过.

编辑:我最终做了什么

>我采用了RequireJs并将所有对象移动到AMD风格的模块中
>我使用Jamine来运行测试
>我使用Sinon来创建模拟和存根
>我使用Squire将mocks和stub存入我测试的系统

请参阅测试文件的coffeescript示例

define ['squire', 'sinon' ], ( squire, sinon ) ->
  describe '==== a view model ====', ->
    sut = null
    testContext = null

    beforeEach ->
      testContext =
        squireInjector: new squire
        stubService: sinon.stub()
        stubJquery: sinon.stub()
        someCallbackSpy: sinon.spy()

      testContext.squireInjector.mock( 
        'jquery', squire.Helpers.returns( stubJquery ) )

      testContext.squireInjector.require ['aViewModel'], ( viewModel ) =>
        sut = new viewModel
          service: testContext.stubService
          someCallback: testContext.someCallbackSpy

      waitsFor( -> sut? )

    afterEach ->
      sut = null
      testContext = null

    describe 'the constructor method should', ->
      it 'create a new instance of the view 
        model and have required dependencies', ->
        expect( sut ).toBeDefined
        expect( sut.service ).toBeDefined
        expect( sut.someCallback ).toBeDefined

    describe 'the next method should', ->
      it 'increment the route id by one', ->
        # Arrange
        sut.routeId = 5

        # Act
        sut.next()

        # Assert
        expect( sut.routeId ).toEqual( 6 )
        expect( testContext.someCallbackSpy.called ).toBe(true)

解决方法:

您可以使用requirejs,以及其中一个解决方案:

> creating a new context and override dependencies with your mocks
> Testr
> SquireJs

或者你只是嘲笑你的对象的原型.

jasmine.spy(Alert.prototype, 'someFunction')

顺便说一句.您可以使用垫片将wire.js与旧浏览器一起使用.来自文档:

To support non-ES5 legacy browsers, wire.js 0.9.x requires poly 0.5.0
or higher. You can clone or download poly into your project, or
install it via yeoman/bower:

上一篇:javascript – CoffeeScript,原型继承和构造函数


下一篇:Ramaze CoffeeScript:是否可以使用Ramaze自动生成Javascript?