77

window.location.hrefを使用する関数の単体テストがいくつかあります。理想的ではありません。むしろこれを渡したかったのですが、実装では不可能です。テストランナーページを実際にURLに移動させずに、この値をモックすることが可能かどうか疑問に思っています。

  window.location.href = "http://www.website.com?varName=foo";    
  expect(actions.paramToVar(test_Data)).toEqual("bar"); 

ユニットテストフレームワークにジャスミンを使用しています。

4

9 に答える 9

56

これを行う最善の方法は、どこかにヘルパー関数を作成し、それをモックすることです。

 var mynamespace = mynamespace || {};
    mynamespace.util = (function() {
      function getWindowLocationHRef() {
          return window.location.href;
      }
      return { 
        getWindowLocationHRef: getWindowLocationHRef
      }
    })();

コードで window.location.href を直接使用する代わりに、代わりにこれを使用してください。次に、モックされた値を返す必要があるときはいつでも、このメソッドを置き換えることができます。

mynamespace.util.getWindowLocationHRef = function() {
  return "http://mockhost/mockingpath" 
};

クエリ文字列パラメーターなど、ウィンドウの特定の部分が必要な場合は、そのためのヘルパー メソッドも作成し、解析をメイン コードから除外します。jasmine などの一部のフレームワークには、関数をモックして目的の値を返すだけでなく、関数が呼び出されたことを検証できるテスト スパイがあります。

spyOn(mynamespace.util, 'getQueryStringParameterByName').andReturn("desc");
//...
expect(mynamespace.util.getQueryStringParameterByName).toHaveBeenCalledWith("sort");
于 2011-08-13T14:04:47.023 に答える
22

以前の投稿で既に示唆されている 2 つの解決策を提案します。

  • アクセスに関する関数を作成し、それを本番コードで使用して、テストで Jasmine を使用してこれをスタブします。

    var actions = {
        getCurrentURL: function () {
            return window.location.href;
        },
        paramToVar: function (testData) {
            ...
            var url = getCurrentURL();
            ...
        }
    };
    // Test
    var urlSpy = spyOn(actions, "getCurrentURL").andReturn("http://my/fake?param");
    expect(actions.paramToVar(test_Data)).toEqual("bar");
    
  • 依存性注入を使用して、テストに偽物を注入します。

    var _actions = function (window) {
        return {
            paramToVar: function (testData) {
                ...
                var url = window.location.href;
                ...
            }
        };
    };
    var actions = _actions(window);
    // Test
    var fakeWindow = {
       location: { href: "http://my/fake?param" }
    };
    var fakeActions = _actions(fakeWindow);
    expect(fakeActions.paramToVar(test_Data)).toEqual("bar");
    
于 2012-01-13T13:24:39.633 に答える
10

windowローカル コンテキストをシミュレートし、独自のバージョンのandwindow.locationオブジェクトを作成する必要があります

var localContext = {
    "window":{
        location:{
            href: "http://www.website.com?varName=foo"
        }
    }
}

// simulated context
with(localContext){
    console.log(window.location.href);
    // http://www.website.com?varName=foo
}

//actual context
console.log(window.location.href);
// http://www.actual.page.url/...

を使用するwithと、すべての変数 ( window! を含む) が最初にコンテキスト オブジェクトから検索され、存在しない場合は実際のコンテキストから検索されます。

于 2011-01-25T10:41:14.113 に答える
6

場合によっては、window.location を変更するライブラリがあり、正常に機能するだけでなくテストも行いたい場合があります。この場合、クロージャを使用して、このようなライブラリに目的の参照を渡すことができます。

/* in mylib.js */
(function(view){
    view.location.href = "foo";
}(self || window));

次に、ライブラリを含める前に、テストで self をグローバルに再定義すると、ライブラリはモックの self をビューとして使用します。

var self = {
   location: { href: location.href }
};

ライブラリでは、次のようなこともできるため、テストの任意の時点で self を再定義できます。

/* in mylib.js */
var mylib = (function(href) {
    function go ( href ) {
       var view = self || window;
       view.location.href = href;
    }
    return {go: go}
}());

すべてではないにしてもほとんどの最新のブラウザーでは、self は既定で既に window への参照になっています。Worker API を実装するプラットフォームでは、Worker self 内にグローバル スコープへの参照があります。node.js では、self と window の両方が定義されていないため、必要に応じて次のようにすることもできます。

self || window || global

node.js が実際に Worker API を実装する場合、これは変更される可能性があります。

于 2011-10-15T19:14:40.693 に答える
4

以下は、window.location.href および/またはグローバル オブジェクト上にある可能性のあるその他のものをモックするために取ったアプローチです。

まず、直接アクセスするのではなく、オブジェクトがゲッターとセッターで保持されるモジュールにカプセル化します。以下は私の例です。私は require を使用していますが、ここでは必要ありません。

define(["exports"], function(exports){

  var win = window;

  exports.getWindow = function(){
    return win;
  };

  exports.setWindow = function(x){
    win = x;
  }

});

さて、通常は のようなコードで行っていたところを、次のようwindow.location.hrefにします。

var window = global_window.getWindow();
var hrefString = window.location.href;

最後に、セットアップが完了し、ウィンドウ オブジェクトを代わりに配置したい偽のオブジェクトに置き換えて、コードをテストできます。

fakeWindow = {
  location: {
    href: "http://google.com?x=y"
  }
}
w = require("helpers/global_window");
w.setWindow(fakeWindow);

これによりwin、ウィンドウ モジュールの変数が変更されます。もともとはグローバルwindowオブジェクトに設定されていましたが、挿入した偽のウィンドウ オブジェクトには設定されていません。したがって、置き換えた後、コードは偽のウィンドウ オブジェクトと、それを配置した偽の href を取得します。

于 2015-07-23T16:05:44.653 に答える
0

IMO、このソリューションは、ソースの window.location.href を $window.location.href に置き換えることができるという点で、cburgmer の小さな改善です。確かに私は Jasmine ではなく Karma を使用していますが、このアプローチはどちらでも機能すると思います。そして、シノンへの依存関係を追加しました。

最初のサービス/シングルトン:

function setHref(theHref) {
    window.location.href = theHref;
}
function getHref(theHref) {
    return window.location.href;
}

var $$window = {
        location: {
            setHref: setHref,
            getHref: getHref,
            get href() {
                return this.getHref();
            },
            set href(v) {
                this.setHref(v);
            }
        }
    };
function windowInjectable() {  return $$window; }

これで、次のように windowInjectable() を $window として挿入することにより、コードで location.href を設定できます。

function($window) {
  $window.location.href = "http://www.website.com?varName=foo";
}

単体テストでそれを嘲笑すると、次のようになります。

sinon.stub($window.location, 'setHref');  // this prevents the true window.location.href from being hit.
expect($window.location.setHref.args[0][0]).to.contain('varName=foo');
$window.location.setHref.restore();

getter / setter 構文は IE 9 に戻り、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/setに従って広くサポートされています。

于 2016-08-12T01:56:13.790 に答える
-1

window.location.href同じページにいる間に偽造する必要があります。私の場合、これは完全に機能しました。

$window.history.push(null, null, 'http://server/#/YOUR_ROUTE');
$location.$$absUrl = $window.location.href;
$location.replace();

// now, $location.path() will return YOUR_ROUTE even if there's no such route
于 2016-08-30T21:09:27.053 に答える