angular2 学习笔记 ( unit test 单元测试 )

更新 2018-06-03框架

spy object 异步

当组件或则服务有对其它服务依赖的时候,咱们一般会把这些依赖写成 spy 或则叫 fake.async

为何这样作的呢 ? ide

主要的缘由是咱们不该该依赖具体的代码,假设具体的代码错了,咱们这个服务也会跟着报错. 单元测试

因此单元测试的 "单元",就是说咱们必须把咱们要测试的东西独立放到一个测试环境里头,对外部任何依赖都作隔离. 测试

若是报错,那么必定是它错了,绝对不能是由于被其它人影响而报错. 因此咱们必须把依赖的服务都写成 spy.this

describe('SecondService', () => {

  let firstServiceSpy: jasmine.SpyObj<FirstService>; // 定义依赖的服务
  
  beforeEach(() => {
    firstServiceSpy = jasmine.createSpyObj('firstService', ['getValue']); //建立假的服务
    firstServiceSpy.getValue.and.returnValue('firstValue'); // 直接设定返回的结果 (这样无论这个服务的具体实现正不正确, 咱们都不会被影响到)
    TestBed.configureTestingModule({
      providers: [
        SecondService,
        { provide: FirstService, useValue: firstServiceSpy } // 替换掉 provide 就能够了
      ]
    });
  });

  it(`getValue should return 'firstValueSecondValue'`, inject([SecondService], (secondService : SecondService) => {    
    expect(secondService.getValue()).toBe('firstValuesecondValue'); 
  }));

});

 

 

第一次写单元测试.url

之前一直都有据说 TDD 的事情. spa

今天总算是去尝试了一下. debug

先说说 TDD 的想法, 是这样的, 

开发项目的流程 : 肯定需求 -> 写类,接口,方法的名字(不写具体实现代码哦) -> 写测试代码 -> 这时测试的话必定是所有 fail 由于实现代码还没写嘛 -> 写实现代码 -> 运行测试 ...  

这样的流程适合须要敏捷开发的项目, 若是你的项目常常须要扩展, 并且扩展每每是不在预计范围内的, 那么你必然须要使用敏捷开发模式和流程. 

也只有把测试写好,之后代码修改了之后才不须要人工的再去测试一遍. 

倒过来看的话,若是你的项目逻辑简单,扩展老是在预计范围呢, 那么你硬去搞敏捷开发写测试代码的话,就有点浪费了. 

 

angular 框架支持测试. 使用 karma , jasmine, cli 来跑。

我的以为要写的好测试, 对 angular 的依赖注入机制要有点基础. 

 

一般咱们会测试的东西是 component 和 service. 

记得不是因此的东西都要测试的,就好像数学考试同样, 不须要每一题都 double check, 只测试那些容易出错的地方就能够了.

那什么地方容易出错呢. 这个因人而异, 看你本身的经验. 

我我的的建议是测试那些关系比较多和复杂的地方. 

 

好比咱们要测试 component 

咱们须要先把 component 的依赖准备好,好比 component 依赖的服务. 

beforeEach(() => {
    TestBed.configureTestingModule({
        imports: [StoogesModule],
        declarations: [
            SimpleComponent
        ],
        providers: [
            MockBackend,
            BaseRequestOptions
        ]
    });
    TestBed.overrideComponent(SimpleComponent, {
        set: {
            providers: [
                {
                    provide: Http,
                    deps: [
                        MockBackend,
                        BaseRequestOptions
                    ],
                    useFactory: (backend: XHRBackend, defaultOptions: BaseRequestOptions) => {
                        return new Http(backend, defaultOptions);
                    }
                }
            ]
        }
    });
    TestBed.compileComponents();
    this.fixture = TestBed.createComponent(SimpleComponent);
    this.com = this.fixture.debugElement.componentInstance;
});

TestBed.configureTestingModule 是让咱们写准备环境的. 它和 NgModule 差很少.

MockBackend 是模拟 http 数据用的

TestBed.overrideComponent 这个方法用来覆盖组件定义好的 provider 

it("test", async(inject([MockBackend], (backend: MockBackend) => {
    const mockResponse = {
        data: [
            { id: 0, name: 'Video 0' },
            { id: 1, name: 'Video 1' },
            { id: 2, name: 'Video 2' },
            { id: 3, name: 'Video 3' },
        ]
    };

    backend.connections.subscribe((connection) => {
        console.log("test");
        connection.mockRespond(new Response(new ResponseOptions({
            body: JSON.stringify(mockResponse)
        })));
    });

    let com = this.com as SimpleComponent;
    com.dada().subscribe(v => {
        expect("haha").toBe("haha");
    });
})));

async() 是帮助咱们写异步的, 放在 It 的方法里面就好了

inject() 天然是依赖注入 service 咯, 这个写法是否是让你想起了 ng1 ? 

backend.connections 是拦截全部的请求, 咱们进一步判断 connection request url 来作出不一样的 response data.

能够看出来,主要的代码都是为了搭建环境. 经过依赖注入去覆盖原有的 provider. 

 

咱们在看看 service.spec.ts

describe("test", () => {
    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                SimpleService
            ]
        });
    });

    it("test1", async(inject([SimpleService], async (simple: SimpleService) => {
        let data = await simple.getData();
        console.log("a");
        expect(data).toBe("a");
    })));
});

这个比较简单, 由于不用 create component and override component provider.

写 await async 也是 ok 的哦. 

相关文章
相关标签/搜索