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


    更新 2018-06-03

    spy object 

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

    为什么这样做的呢 ? 

    主要的原因是我们不应该依赖具体的代码,假设具体的代码错了,我们这个服务也会跟着报错. 

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

    如果报错,那么一定是它错了,绝对不能是因为被其它人影响而报错. 所以我们必须把依赖的服务都写成 spy.

    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'); 
      }));
    
    });

    第一次写单元测试.

    以前一直都有听说 TDD 的事情. 

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

    先说说 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 的哦. 

  • 相关阅读:
    双链表 teacherboubleloopnohead
    System.Reflection(温习二)
    在地址栏调试js(小技巧)
    在vs2005中的ReportViewer(RDLC报表)中使用直接打印功能,在vs2005使用ReportViewer2008
    .net的手动编译类方法
    System.Reflection(温习)
    https://imo.im/
    SOA是什么(转)
    ASP.NET的编译方法(转,复习一下)
    动态生成一个继承接口的类
  • 原文地址:https://www.cnblogs.com/keatkeat/p/6440806.html
Copyright © 2020-2023  润新知