调试$ rootScope的无限摘要。$ apply in unit tests

时间:2016-07-11 00:50:05

标签: javascript angularjs unit-testing

我对我的UserService进行了简单测试,调用了我的ApiService。我使用的是第三方API SDK,因此我无法直接使用$httpBackend,但我已将其设置为至少现在从API返回空数据:< / p>

// 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调用调用SDK的ApiService。这将设置在UserService上设置的内部registerId

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

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

有没有其他方法可以解决承诺或模拟此API?一般来说,如何从$rootScope.$apply正确调试导致无限消化周期的内容?它似乎没有在循环中调用registerUser

1 个答案:

答案 0 :(得分:1)

真正的罪犯可能位于不相关的代码中,路由器最常参与无限摘要。

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

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

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