冗談

2017-07-14 12 views
14

正しく次の例を模擬するための最良の方法は何ですか?冗談

問題は、インポート後に、fooが元のロック解除されたbarへの参照を保持していることです。

module.js:

export function bar() { 
    return 'bar'; 
} 

export function foo() { 
    return `I am foo. bar is ${bar()}`; 
} 

module.test.js:

import * as module from '../src/module'; 

describe('module',() => { 
    let barSpy; 

    beforeEach(() => { 
     barSpy = jest.spyOn(
      module, 
      'bar' 
     ).mockImplementation(jest.fn()); 
    }); 


    afterEach(() => { 
     barSpy.mockRestore(); 
    }); 

    it('foo',() => { 
     console.log(jest.isMockFunction(module.bar)); // outputs true 

     module.bar.mockReturnValue('fake bar'); 

     console.log(module.bar()); // outputs 'fake bar'; 

     expect(module.foo()).toEqual('I am foo. bar is fake bar'); 
     /** 
     * does not work! we get the following: 
     * 
     * Expected value to equal: 
     * "I am foo. bar is fake bar" 
     * Received: 
     * "I am foo. bar is bar" 
     */ 
    }); 
}); 

ありがとう!

EDIT:

export function foo() { 
    return `I am foo. bar is ${exports.bar()}`; 
} 

export function foo() { 
    return `I am foo. bar is ${bar()}`; 
} 

をしかし、これは、pです:私は変更することができます。どこにでも行うには私の意見では醜い:/

答えて

2

FWIW、私はに落ち着いソリューションは、デフォルトの引数を設定することにより、dependency injectionを使用していました。

だから私は、これは私のコンポーネントのAPIに破壊変更ではありません、と私は簡単に次のよう

を行うことによって、私のテストでバーを無効にすることができます

export function bar() { 
    return 'bar'; 
} 

export function foo (_bar = bar) { 
    return `I am foo. bar is ${_bar()}`; 
} 

export function bar() { 
    return 'bar'; 
} 

export function foo() { 
    return `I am foo. bar is ${bar()}`; 
} 

を変更します

これは、やや良いテストコードにつながるという利点もあります:)

+0

あなたが許可されているので、私は、一般的に依存性注入のファンではありませんコードの書き方を変更するためのテスト。それは言われている、これは現在のより高い投票率の答えよりも醜いです – Sean

9

問題は、あなたがバーのスコープが解決されることを期待する方法に関連しているようです。一方

module.jsであなたが(代わりにこの2つの機能を保持しているオブジェクトの)二つの機能をエクスポートします。モジュールがエクスポートされる方法のため、エクスポートされた物のコンテナへの参照はあなたがそれを言及したようにexportsです。

一方、これらの機能を保持しているオブジェクトのようなエクスポート(その別名module)を処理し、その機能の1つ(ファンクションバー)を置き換えようとします。

あなたのfooの実装をよく見ると、あなたが実際にバー機能に一定の基準を保持しています。

あなたは、あなたがちょうど実際にfooが実際にあなたが持っているバーの別のバージョンを使用するようにするには、あなたのmodule.test.js

の範囲に参照コピーを置き換える新しいものとバー機能を置き換えると思います二つの可能性:

module.js:module.jsで

  1. がfooとバー方式の両方を保持する、クラスまたはインスタンスをエクスポート

    export class MyModule { 
        function bar() { 
        return 'bar'; 
        } 
    
        function foo() { 
        return `I am foo. bar is ${this.bar()}`; 
        } 
    } 
    

    注fooメソッドでこのキーワードを使用。

    Module.test.js:

    import { MyModule } from '../src/module' 
    
    describe('MyModule',() => { 
        //System under test : 
        const sut:MyModule = new MyModule(); 
    
        let barSpy; 
    
        beforeEach(() => { 
         barSpy = jest.spyOn(
          sut, 
          'bar' 
        ).mockImplementation(jest.fn()); 
        }); 
    
    
        afterEach(() => { 
         barSpy.mockRestore(); 
        }); 
    
        it('foo',() => { 
         sut.bar.mockReturnValue('fake bar'); 
         expect(sut.foo()).toEqual('I am foo. bar is fake bar'); 
        }); 
    }); 
    
  2. あなたが言ったように、グローバルexportsコンテナ内のグローバル参照を書き換えます。エクスポートを初期状態に正しくリセットしないと、他のテストで奇妙な動作が導入される可能性があるため、これはお勧めできません。

1

別の解決策として、モジュールを独自のコードファイルにインポートし、エクスポートされたすべてのエンティティのインポートされたインスタンスを使用することができます。このように:

barのエクスポートインスタンス使用している fooので今、 barは本当に簡単ですからかっ
import * as thisModule from './module'; 

export function bar() { 
    return 'bar'; 
} 

export function foo() { 
    return `I am foo. bar is ${thisModule.bar()}`; 
} 

:独自のコードにモジュールをインポートする

import * as module from '../src/module'; 

describe('module',() => { 
    it('foo',() => { 
     spyOn(module, 'bar').and.returnValue('fake bar'); 
     expect(module.foo()).toEqual('I am foo. bar is fake bar'); 
    }); 
}); 

は奇妙に見えますが、原因にES6さんサイクリックインポートのサポート、それは本当にスムーズに動作します。

0

エクスポートを定義すると、関数をエクスポートオブジェクトの一部として参照できます。次に、あなたのモック内の関数を個別に上書きすることができます。これは、インポートがコピーではなく参照として機能するためです。

module.js:

exports.bar() => { 
    return 'bar'; 
} 

exports.foo() => { 
    return `I am foo. bar is ${exports.bar()}`; 
} 

module.test.js:

describe('MyModule',() => { 

    it('foo',() => { 
    let module = require('./module') 
    module.bar = jest.fn(()=>{return 'fake bar'}) 

    expect(module.foo()).toEqual('I am foo. bar is fake bar'); 
    }); 

}) 
関連する問題