首页 > 解决方案 > 在 Angular 中,我为什么要使用 jasmine.createSpyObj 而不是简单地将对象传递给提供者的 useValue?

问题描述

我刚刚开始使用 Angular 和单元测试,我想测试Component一个依赖于ActivatedRoute.

Component有一个ngOnInit看起来像这样的方法:

async ngOnInit() {
    const id = Number(this.route.snapshot.paramMap.get('id'));
    //get data using the id
}

所以在我的测试beforeEach功能中,我试图像这样设置测试平台(注意,这是我开始测试之前):

    let mockRoute;

    beforeEach(async () => {
        //this example didn't work, the test failed trying to reach the .get('id') call
        mockRoute = jasmine.createSpyObj('mockRoute', ['snapshot.paramMap.get']);
        await TestBed.configureTestingModule({
            providers: [{ provide: ActivatedRoute, mockRoute }],
            declarations: [ MyComponentToTest ]
        })
        .compileComponents();
    });

我之所以使用它jasmine.createSpyObj是因为我遵循了一个复数示例,但是在上面的示例不起作用之后,我最终在互联网上找到了这个:

beforeEach(async () => {
    //this example worked
    await TestBed.configureTestingModule({
        providers: [
        {
            provide: ActivatedRoute,
            useValue: {
                snapshot: {
                    paramMap: {
                        get: () => 1
                    }
                }
            }
        }],
        declarations: [ MyComponentToTest ]
    })
    .compileComponents();
});

我看到了大量关于使用jasmine.createSpyObj创建模拟的文档(和复数视频),但在我的情况下,它的效果不如useValue,那么有人知道为什么有人会使用它jasmine.createSpyObj吗?它是否存在用于useValue无法使用的非常特定的用途?

标签: angularunit-testingjasmine

解决方案


jasmine.createSpyObj用来模拟public一个类的方法。public它在模拟实例变量方面做得不好。

// the first string argument in jasmine.createSpyObj is for debugging purposes, basically it will say
// publicNameForDebugging.names was not called
// the second argument is an array of strings of public methods you would like to mock
mock = jasmine.createSpyObj('publicNameForDebugging', ['names', 'of', 'public', 'methods'])

对于您的情况,对于激活的路由,您没有要模拟的公共方法,但以下应该使用 createSpyObj 工作:

    let mockRoute;

    beforeEach(async () => {
        //this example didn't work, the test failed trying to reach the .get('id') call
        // have to put 'anything' because you might get an error if the second argument
        // is an empty array
        mockRoute = jasmine.createSpyObj('mockRoute', ['anything']);
        // mock the instance variables and attach them to the spyObj just created
        mockRoute.snapshot = {};
        mockRoute.snapshot.paramMap = {};
        mockRoute.snapshot.paramMap.get = () => 1;
        await TestBed.configureTestingModule({
            providers: [{ provide: ActivatedRoute, mockRoute }],
            declarations: [ MyComponentToTest ]
        })
        .compileComponents();
    });

推荐阅读