5

次のプロバイダーがあります。

angular.module('MyApp').provider('MyDevice', function () {

    var ngInjector = angular.injector(['ng']),
        $window = ngInjector.get('$window');

    function isMobileDevice () {
        return (/iPhone|iPod|iPad|Silk|Android|BlackBerry|Opera Mini|IEMobile/)
            .test($window.navigator.userAgent || $window.navigator.vendor || $window.opera);
    }

    this.$get = function () {
        return {
            isDesktop: function () {
                return !isMobileDevice();
            },
            isMobile: function () {
                return isMobileDevice();  
            }
        };
    };

});

そして、次のテスト仕様:

describe('MyDeviceProvider', function () {

    var myDevice;

    beforeEach(function () {
        inject(['MyDevice', function (_myDevice_) {
            myDevice = _myDevice_;
        }]);
    });

    it('Test #1', function () {
        // Mock '$window.navigator.userAgent' to "desktop"
        expect(myDevice.isDesktop()).toEqual(true);
        expect(myDevice.isMobile()).toEqual(false);
    });

    it('Test #2', function () {
        // Mock '$window.navigator.userAgent' to "mobile"
        expect(myDevice.isDesktop()).toEqual(false);
        expect(myDevice.isMobile()).toEqual(true);
    });

});

私の質問は、どうすれば$window両方をモックしTest #1Test #2成功させることができるでしょうか? $provide.value無数のオブジェクトを試してみましたが、テストを実行spyOnする価値をあざけることができないようです。$window.navigator.userAgent

これを解決するにはどうすればよいですか?

PS: 上記のコードは、私の問題のデモンストレーションとしてのみ機能し、アプリケーションの特別な要件のため、プロバイダーをサービスに変更できません。

4

1 に答える 1

16

非常に大雑把に言えば、次のことができます。

describe('MyDeviceProvider', function () {

    var myDevice,
        $window,
        navigator;

    beforeEach(function () {
        inject(['MyDevice', '$window', function (_myDevice_, _$window_) {
            myDevice = _myDevice_;
            $window = _$window_;
        }]);

        // Save the original navigator object
        navigator = $window.navigator;
    });

    afterEach(function () {
        $window.navigator = navigator;
    });

    it('Test #1', function () {
        // Mock the entire navigator object to "desktop"
        $window.navigator = {
            userAgent: "desktop" // Use a real "desktop" user agent
        };

        // Mock '$window.navigator.userAgent' to "desktop"
        expect(myDevice.isDesktop()).toEqual(true);
        expect(myDevice.isMobile()).toEqual(false);
    });

    it('Test #2', function () {
        // Mock the entire navigator object to "desktop"
        $window.navigator = {
            userAgent: "mobile" // Use a real "mobile" user agent
        };
        // Mock '$window.navigator.userAgent' to "mobile"
        expect(myDevice.isDesktop()).toEqual(false);
        expect(myDevice.isMobile()).toEqual(true);
    });

});

さまざまなブラウザーを模倣したさまざまなモックもテストする必要があります。

于 2014-07-11T16:15:54.117 に答える