Jasmine 2.0 async done() 和 angular-mocks inject() 在同一个测试 it()

Posted

技术标签:

【中文标题】Jasmine 2.0 async done() 和 angular-mocks inject() 在同一个测试 it()【英文标题】:Jasmine 2.0 async done() and angular-mocks inject() in same test it() 【发布时间】:2014-10-06 02:29:43 【问题描述】:

我平时的测试用例是这样的

it("should send get request", inject(function(someServices) 
     //some test
));

Jasmine 2.0 异步测试应该是这样的

it("should send get request", function(done) 
     someAsync.then(function()
         done();
     );
);

如何在一个测试中同时使用 done 和 injection?

【问题讨论】:

【参考方案1】:

这应该有效;我更新到 Jasmine 2.0 时遇到了同样的问题

it("should send get request", function(done) 
    inject(function(someServices) 
        //some async test
        done();
    )(); // function returned by 'inject' has to be invoked
);

【讨论】:

对我来说这行不通。 inject 中的代码根本不会被调用。 @WhiteAngel,我上次遇到您描述的问题时,是因为 karma.conf.js 的 files 列表中缺少我的应用程序所需的一些依赖项。使用phantomJS 来调试它是不可能的,因为它提供的错误消息远远不够。如果您还没有弄清楚问题的根源,请尝试使用 Chrome 或 FF 作为测试浏览器。 这对我不起作用。 inject的返回值是一个函数,需要调用。 @WhiteAngel @dokkaebi 在给出的代码示例中,立即调用从inject 返回的方法。这是超级重要的!如果你最后忘记了这两个括号,你的测试代码将不会被执行。【参考方案2】:

重要的注意事项是inject 调用后的括号。例如。

inject(function(someServices) 
   //some async test
   done();
)();  <-- these brackets here important.

如果看inject的类型:

export declare function inject(tokens: any[], fn: Function): () => any;

你可以看到它返回一个函数,所以你没有得到任何输出,因为你忘了调用这个函数!!

如果你仔细想想,它返回一个函数是有道理的,因为it 接受了一个函数!

所以额外的括号应该可以解决所有问题!

工作示例:

  it('should allow you to observe for changes', function(done) 
    inject([GlobalStateService], (globalStateService: GlobalStateService) => 
      globalStateService.observe("user", storageType.InMemoryStorage, (user: string) => 
        expect(user).toBe("bla");
        done();
      );

      globalStateService.write( user: "bla", storageType.InMemoryStorage);
    )();
  );

【讨论】:

我认为这可以作为答案。无论如何,评论都太长了。【参考方案3】:

补充@Scott Boring 的答案和@WhiteAngel 的评论,他们提到从未调用过inject 中的代码。

这对我有用:

it("should send get request", function(done) 
    inject(function(someServices) 
       //some async test
       done();
    )();
);

【讨论】:

有道理。 inject 的正常用法是将其返回值 (() =&gt; any) 作为第二个参数传递给 it,它由 jasmine 调用。所以我们必须调用inject返回的函数才能运行! 我得到inject is not a function这个【参考方案4】:

你可以这样写测试:

describe("Some service'", function ()     
    var service;
    var data;

    beforeEach(function (done)    

        module('app');

        inject(function (someService) 
            service = someService;
        );

        service
            .getData()
            .then(function(result) 
                data = result;
                done();
            );
    ); 

    it('should return a result', function ()   
        expect(data).toBeDefined();
    ); 

【讨论】:

【参考方案5】:

对于 Angular 5.2.0:@scott-boring 的方法对我不起作用。起作用的是使用TestBed.get() 而不是inject() 来获取服务,如docs 中所述:

describe('TooltipComponent', () => 
  let component: TooltipComponent;
  let fixture: ComponentFixture<TooltipComponent>;
  let myService: MyService;

  beforeEach(async(() => 
    const myServiceSpy = jasmine.createSpyObj('MyService', ['calc']);

    TestBed.configureTestingModule(
      declarations: [ MyComponent ],
      providers: [
        provide: MyService, useValue: myServiceSpy
      ]
    )
    .compileComponents();

    myService = TestBed.get(MyService);
  ));

  beforeEach(() => 
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  );

  it('should render correctly', (done) => 
    component.render();

    setTimeout(() => 
      expect(myService.calc).toHaveBeenCalled();
      done();
    , 1000);
  );

【讨论】:

以上是关于Jasmine 2.0 async done() 和 angular-mocks inject() 在同一个测试 it()的主要内容,如果未能解决你的问题,请参考以下文章

在异步超时时传递Jasmine规范

如何在退出 Jasmine 测试之前测试 Observable 是不是已发布事件?

简洁的 async await

nodejs async series 小白向

使用 Jasmine 进行 Angular 单元测试:如何删除或修改 spyOn

如何使用async-await然后在一个Mocha测试中完成?