首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在ember.js中进行单元测试视图?

如何在ember.js中进行单元测试视图?
EN

Stack Overflow用户
提问于 2013-02-15 21:02:52
回答 2查看 2.5K关注 0票数 14

我们正在学习Ember.js。我们做了所有的开发TDD,并且希望Ember.js也不例外。我们有构建测试驱动的Backbone.js应用程序的经验,所以我们熟悉使用Jasmine或Mocha/柴测试前端代码。

在研究如何测试视图时,当视图的模板有一个#linkTo语句时,我们遇到了一个问题。不幸的是,我们无法找到好的测试示例和实践。这个要点是我们寻求如何得到正确的单元测试成员应用程序的答案。

在查看linkTo在Ember.js源代码中的测试时,我们注意到它包含一个支持#linkTo的ember应用程序的完整连接。这是否意味着我们在测试模板时不能对此行为进行存根处理?

如何使用模板呈现为成员视图创建测试?

下面是带有我们的测试的要点和一个将使测试通过的模板,以及一个会使其失败的模板。

view_spec.js.coffee

代码语言:javascript
复制
# This test is made with Mocha / Chai,
# With the chai-jquery and chai-changes extensions

describe 'TodoItemsView', ->

  beforeEach ->
    testSerializer = DS.JSONSerializer.create
      primaryKey: -> 'id'

    TestAdapter = DS.Adapter.extend
      serializer: testSerializer
    TestStore = DS.Store.extend
      revision: 11
      adapter: TestAdapter.create()

    TodoItem = DS.Model.extend
      title: DS.attr('string')

    store = TestStore.create()
    @todoItem = store.createRecord TodoItem
      title: 'Do something'

    @controller = Em.ArrayController.create
      content: []

    @view = Em.View.create
      templateName: 'working_template'
      controller: @controller

    @controller.pushObject @todoItem

  afterEach ->
    @view.destroy()
    @controller.destroy()
    @todoItem.destroy()

  describe 'amount of todos', ->

    beforeEach ->
      # $('#konacha') is a div that gets cleaned between each test
      Em.run => @view.appendTo '#konacha'

    it 'is shown', ->
      $('#konacha .todos-count').should.have.text '1 things to do'

    it 'is livebound', ->
      expect(=> $('#konacha .todos-count').text()).to.change.from('1 things to do').to('2 things to do').when =>
        Em.run =>
          extraTodoItem = store.createRecord TodoItem,
            title: 'Moar todo'
          @controller.pushObject extraTodoItem

broken_template.handlebars

代码语言:javascript
复制
<div class="todos-count"><span class="todos">{{length}}</span> things to do</div>

{{#linkTo "index"}}Home{{/linkTo}}

working_template.handlebars

代码语言:javascript
复制
<div class="todos-count"><span class="todos">{{length}}</span> things to do</div>
EN

回答 2

Stack Overflow用户

发布于 2013-02-17 03:43:22

我们的解决方案基本上是加载整个应用程序,但尽可能地隔离测试对象。例如,

代码语言:javascript
复制
describe('FooView', function() {
  beforeEach(function() {
    this.foo = Ember.Object.create();
    this.subject = App.FooView.create({ foo: this.foo });
    this.subject.append();
  });

  afterEach(function() {
    this.subject && this.subject.remove();
  });

  it("renders the foo's favoriteFood", function() {
    this.foo.set('favoriteFood', 'ramen');
    Em.run.sync();
    expect( this.subject.$().text() ).toMatch( /ramen/ );
  });
});

也就是说,路由器和其他全局都是可用的,所以它不是完全隔离的,但是我们可以很容易地为更接近被测试对象的东西发送双值。

如果您真的想隔离路由器,linkTo助手会将其查找为controller.router,因此您可以这样做。

代码语言:javascript
复制
this.router = {
  generate: jasmine.createSpy(...)
};

this.subject = App.FooView.create({
  controller: { router: this.router },
  foo: this.foo
});
票数 9
EN

Stack Overflow用户

发布于 2013-11-19 23:02:15

处理这一问题的一种方法是为linkTo助手创建一个存根,然后将其使用在一个前置块中。这将绕过实际linkTo的所有额外需求(例如路由),并让您专注于视图的内容。我就是这样做的:

代码语言:javascript
复制
// Test helpers
TEST.stubLinkToHelper = function() {
    if (!TEST.originalLinkToHelper) {
        TEST.originalLinkToHelper = Ember.Handlebars.helpers['link-to'];
    }
    Ember.Handlebars.helpers['link-to'] = function(route) {
        var options = [].slice.call(arguments, -1)[0];
        return Ember.Handlebars.helpers.view.call(this, Em.View.extend({
            tagName: 'a',
            attributeBindings: ['href'],
            href: route
        }), options);
    };
};

TEST.restoreLinkToHelper = function() {
    Ember.Handlebars.helpers['link-to'] = TEST.originalLinkToHelper;
    TEST.originalLinkToHelper = null;
};

// Foo test
describe('FooView', function() {
    before(function() {
        TEST.stubLinkToHelper();
    });

    after(function() {
        TEST.restoreLinkToHelper();
    });

    it('renders the favoriteFood', function() {
        var view = App.FooView.create({
            context: {
                foo: {
                    favoriteFood: 'ramen'
                }
            }
        });

        Em.run(function() {
            view.createElement();
        });

        expect(view.$().text()).to.contain('ramen');
    });
});
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14903273

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档