バックグラウンド
Backbone.sync を置き換える Backbone.jsのBackbone.dualStorageプラグインのテストに取り組んでいます。
これはブラウザ プラグインですが、jasmine-node を使用してテストしています。window
vm.createContext を使用してブラウザーをシミュレートするために、coffeescript ソースをノード環境にロードします。
vm = require 'vm'
fs = require 'fs'
coffee = require 'coffee-script'
backboneDualstoragePath = './backbone.dualstorage.coffee'
source = fs.readFileSync(backboneDualstoragePath, 'utf8')
window = require('./global_test_context.coffee').window
context = vm.createContext window
coffee.eval source, sandbox: context, filename: backboneDualstoragePath
exports.window = context
これはうまく機能します。私のテストでは、にアクセスできますwindow.foo
。foo は、global_test_context.coffee のウィンドウ オブジェクトにエクスポートされた属性です。
Jasmine スパイを使用して、ウィンドウ サンドボックスの下にネストされたオブジェクトのメソッドを再定義できます。例えば:
spyOn(window.Store.prototype, 'create').andReturn(true)
window.Store.create() # The spy is called
window.localsync.create() # This function instantiates a Store object and calls create on it
# The spy is called
ただし、コンテキストの直接属性をスパイまたは変更しようとすると、サンドボックス コンテキスト内で変更が見られません。
spyOn(window, 'localsync').andReturn(true)
window.localsync() # The spy is called
window.dualsync() # This function references the global localsync
# The original localsync is called
vm.createContext のドキュメントには次のように書かれています。
(V8) コンテキストは、組み込みオブジェクトと関数のセットと共にグローバル オブジェクトで構成されます。オプションの引数 initSandbox は、コンテキストによって使用されるグローバル オブジェクトの初期コンテンツをシードするために浅いコピーされます。
したがって、属性をウィンドウ変数から vm コンテキストにコピーするように思えます。この時点以降にスパイまたはその他の方法で変更する場合window
は、vm コンテキストを使用して、.xml という名前の属性としてエクスポートしますwindow
。したがって、上記の段落は無関係だと思いますが、間違っている場合に備えて含めたいと思いました。
質問
イベントの流れは次のようになります。
window = vm.createContext({globalVariables: forTesting...})
# similiar to vm.runInContext(backboneDualstorageSource, window)
coffee.eval(backboneDualstorageSource, sandbox: window)
# localsync and dualsync are both defined in the backboneDualstorageSource
spyOn(window, 'localsync')
window.dualsync() # calls the original localsync instead of the spy
VM コンテキストの属性を変更した後、VM 内の「グローバル」属性/関数への参照が変更されないのはなぜですか? これを理解したい。
テスト中のブラウザ スクリプトで /spyOn グローバルを変更できるようにするには、どうすればこれを回避できますか?
ソースを自由に見て、この質問のスニペットと比較して、実際にどのように記述されているかをよく理解してください。
編集
残りのテスト済みコードと同様に、コンテキストで実行される eval 内にスパイを作成することで、この問題を回避することができました。https://github.com/nilbus/Backbone.dualStorage/commit/eb6c2b21を参照してください
グローバル変数にアクセスできるにもかかわらず、コンテキスト内ではグローバル変数を変更できるが、コンテキスト外では変更できない理由を誰かが説明できますか?