在单元测试中调试 $rootScope.$apply 的无限摘要



我对调用我的ApiService的用户服务进行了简单的测试。我使用的是第三方 API SDK,所以我不能直接使用$httpBackend,但我已经设置了它,以便至少现在从 API 返回空数据:

// ApiService mock
beforeEach(module($provide =>
    $provide.factory("ApiService", $q => ({
        request: () => $q.resolve({data: {}}),
    }))
));
// Test
describe("registerUser", () => {
    it("registers user", () => {
        const registerId = "registerId";
        $window.SDK = {credentials: {registerId}};
        UserService.registerUser("socialId", "email");
        $rootScope.$apply();
        expect(UserService.registerId).to.equal(registerId);
    });
});
// Implementation
function UserService(ApiService, $window) {
    let service = {};
    service.registerUser = (socialId, email) => {
        return ApiService.request("registerUser", {socialId, email}).then(response => {
            service.registerId = $window.SDK.credentials.registerId;
        });
    };
    return service;
}

本质上,UserService调用ApiService,ApiService调用SDK。这将设置在用户服务上设置的内部registerId

我正在使用$rootScope.$apply来解决承诺。事实上,如果我确实调用它,我确认registerId设置得当。但是,我得到了[$rootScope:infdig] 10 $digest() iterations reached. Aborting!

如果我不使用$rootScope.$apply承诺永远不会解决,registerId永远不会被设定。

有没有其他方法可以解决承诺或模拟此 API?通常,如何正确调试导致此$rootScope.$apply无限摘要循环的原因?它似乎没有在循环中调用registerUser

真正的罪犯可能位于不相关的代码中,路由器最常在无限摘要中贡献部分。

单元测试假定单元与其他移动部件隔离进行测试。最好不要将与路由器相关的模块加载到路由器测试中不涉及的规范中(这同样适用于影响整个应用程序的任何其他单元)。

在这种情况下,路由模块(例如 app.router)依赖于路由器模块(ui.routerngRoute),只能由顶部模块(app)加载,而不能由其他模块加载。

app.router单元本身可能包含configrun块,这些块设置路由并通过模拟路由器提供商(ngRouter的情况下$routeProvider)和用于路由定义的间谍方法($routeProvider.when等)进行测试。

最新更新