【问题标题】:Testing an Angular Service with stubs使用存根测试 Angular 服务
【发布时间】:2020-04-09 00:20:12
【问题描述】:

我遇到的问题是,每个测试都应该能够以任何顺序运行,但是,我希望能够测试不同的结果。

My DataStorageService 是一项外推所用存储的服务。比如LocalStorage、NoSQL等都可以用,但是我的主代码会继续调用DAtaStorageService。我只是更改实现以使用我需要的任何模块或它们的组合。

这是测试设置之外的示例块。

const BadData:Observable<ITestInterface> = of<ITestInterface>( { Key_: 'Bad', Name: 'Bad Record for Testing' } );
const GoodData:Observable<ITestInterface> = of<ITestInterface>( { Key_: 'Good', Name: 'Good Record for Testing' } );
const NoKey:Observable<ITestInterface> = of<ITestInterface>( { Name: 'Missing Key for Testing' } );

describe('DataStorage Service - Mocked AngularFire Responses', () => {
    let ServiceUnderTest:DataStorage<ITestInterface>;
    let DependentService:AngularFireDatabase;

    const ObjectStub = {
        valueChanges: jasmine.createSpy('valueChanges').and.returnValue(GoodData)
    };

    const AfDbStub = {
        object: jasmine.createSpy('object').and.returnValue(ObjectStub)
    };

    afterEach(() => {
        DependentService = null;
        ServiceUnderTest = null;
    });

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                DataStorage,
                { provide: AngularFireDatabase, useValue:AfDbStub }
            ]
        });
        DependentService = TestBed.inject(AngularFireDatabase);
        ServiceUnderTest = TestBed.inject(DataStorage);
    });

然后我的问题是如何继续设置要返回的存根。我正在编写测试来处理成功返回、负返回等。但是,当我看到构建存根返回时,返回一个值,这些似乎都是单一样式的返回,除非你配置第一个返回,第二个返回,然后是第三个,等等。

该示例注入了一项服务,但它只有一个来自 AngularFire 服务的存根供我的代码使用。因此,我需要为三个不同的测试中的每一个都做这个完整的块。有没有办法在没有 3 个不同的描述块的情况下做到这一点?我知道我可以将其设置为在第一次调用、第二次调用和第三次调用时获得 3 个返回,并且每个测试都会进行适当数量的调用,但是这感觉不对。

但是,由于我想测试成功、失败、丢失数据,以指定顺序返回数据的模拟,意味着我的测试必须按该顺序运行,这意味着它们并不是真正独立的。这是正确的,还是我只是做一些简单的事情,比如返回不同的设置,对否定的测试会使第一次调用得到肯定的结果,然后在同一个测试中进行第二次调用,所以它返回失败并测试结果?

编辑:我也相信我的间谍/存根未正确设置以与底层 Angularfire 一起使用。我的问题仍然是关于替换的,但也许间谍可以在返回中设置函数以允许我检查变量并返回好、坏或错误?

【问题讨论】:

    标签: angular unit-testing angularfire2


    【解决方案1】:

    我更喜欢这样的测试服务:

    { provide: AngularFireDatabase, useValue: {} } // simple empty object
    

    然后在每个测试中你可以使用spyOn 函数来模拟一些结果,例如:

    it('success', () => {
      spy = jasmine.spyOn(dependentService, 'method').andReturn(42);
    
      expect(service.method()).toEqual(...);
      expect(spy).toHaveBeenCalled();
    });
    

    在这种情况下,您可以轻松地控制依赖服务在不同测试场景中的行为方式。

    【讨论】:

    • 谢谢你,因为它看起来更容易。因为我需要返回数据,所以我可以简单地使用 of() 为对象方法创建一个 observable,对吗?
    • 试图返回一个主题仍然给我带来麻烦。
    • 试图了解如何添加对象 (AngularFireDatabase.object(/some/path/) 它将在 andReturn 中返回
    • 如果你希望你的模拟返回of/Subject,或者来自间谍的任何其他异步对象,你应该使用例如:expect(output).toBeObservable(expected); 断言。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    • 2023-01-30
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多