如何让业力/茉莉花单元测试在承诺后使用回调?

How to get karma/jasmine unit tests working with a callback after a promise?

提问人:user1261710 提问时间:4/23/2019 更新时间:4/24/2019 访问量:425

问:

我正在用 AngularJS 1.5、JavaScript 和 Cordova 编写一个应用程序。

我想编写一个单元测试,以检查某些代码是否在承诺后执行。

这是我的代码笔:https://codepen.io/aubz/pen/yrxqxE

我不确定为什么,但单元测试一直说这个错误: 预期的间谍尝试GeoClocking已被调用。

这很奇怪,因为控制台日志打印出来,所以实际上正在调用该函数。

it('if location services are on, proceed', function () {

    spyOn(CordovaDiagnostics, 'getLocationServicesStatus').and.callFake(function () {
        return Promise.resolve(true);
    });

    spyOn(Clocking, 'attemptGeoClocking').and.callFake(function () {});

    Clocking.geolocationClocking();

    expect(Clocking.attemptGeoClocking).toHaveBeenCalled();

});


function geolocationClocking() {

    CordovaDiagnostics
        .getLocationServicesStatus()
        .then(attemptGeoClocking)
        .catch(function () {});
}

function attemptGeoClocking() {
    console.log(' here ');
}
angularjs 单元测试 回调 karma-jasmine

评论


答:

1赞 Frederik Prijck 4/24/2019 #1

基本上,您正在监视错误的功能。让我重命名一些内容,以便更清楚地了解您在做什么:

function Clocking(CordovaDiagnostics) {

    return {
        geolocationClocking: geolocationClocking,
        attemptGeoClockingOUTER: attemptGeoClockingINNER//private API
    };

    function geolocationClocking() {

        CordovaDiagnostics
            .getLocationServicesStatus()
            .then(attemptGeoClockingINNER)
            .catch(function () {});
    }

    function attemptGeoClockingINNER() {
        console.log(' here ');
    }
}

在测试中:

spyOn(Clocking, 'attemptGeoClockingOUTER').and.callFake(function () {
      console.log('calling fake')
 });

正如你所看到的,你的代码正在监视 OUTER 但从不调用 OUTER,而是使用 INNER:geolocationClocking

CordovaDiagnostics
            .getLocationServicesStatus()
            .then(attemptGeoClockingINNER)

您需要以这样一种方式重新编写代码,使其在内部使用与您在测试中存根的函数相同的函数。 下面是一个有效的代码笔:https://codepen.io/anon/pen/xeyrqy?editors=1111

注意:我还替换了 并添加了 ,这是解决承诺所必需的。Promise.resolve$q.when$rootScope.$apply()

添加我在此处所做的更改,以防代码笔消失:

我已将工厂更改为服务(虽然不是必需的,但在这种情况下我更喜欢使用服务):

myApp.service("Clocking", Clocking);

function Clocking(CordovaDiagnostics) {

    this.geolocationClocking = function() {

        CordovaDiagnostics
            .getLocationServicesStatus()
            .then(() => this.attemptGeoClocking())
            .catch(function () {});
    }

    this.attemptGeoClocking = function() {
        console.log(' here ');
    }
}