2017-10-19 1 views
2

Ich habe ein Modul, das importierte Klassen instanziiert und Methoden dieser Instanzen asynchron aufruft.Mock-Abhängigkeitsklassen pro getestete Instanz

Wie kann ich diese Methoden unabhängig voneinander pro Testfall verhöhnen, so dass diese Mocks nur zum Beispiel Sinn machen, die in einem Testfall erstellt werden, da ich Mocks am Ende des Tests nicht zuverlässig wiederherstellen kann?

Beispiel:

// tested class 
import B from './b'; 
import C from './c'; 

export default class A { 
    someFunction() { 
    let instanceB = new B(); 
    return instanceB.doSomething() 
     .then(() => this.doSomethingElse()) 
     .then((data) => { 
     // async context, other tests will start before this. 
     let instanceC = new C(data); 
     }); 
    } 
} 

// test 
import A from './a'; 
describe('test',() => { 
    it('case1',() => { 
    a = new A(); 
    // Mock B, C with config1 
    return a.someFunction().then(() => {/* asserts1 */ }); 
    }) 
    it('case2',() => { 
    a = new A(); 
    // Mock B, C with config2 
    return a.someFunction().then(() => {/* asserts2 */ }); 
    }) 
}) 

Wenn ich B und C in case1 spotten und diese wiederherstellen, synchron, wird C Config überschrieben werden, da case2 vor in dem Asynchron-Kontext C der Instanziierung läuft. Aus dem gleichen Grund kann ich Mocks nicht asynchrons nach assets1 wiederherstellen.

Es gibt ähnliche Fragen: Stubbing a class method with Sinon.js, How to mock dependency classes for unit testing with mocha.js? , aber sie decken nicht das Problem der asynchronen Mocks.

Antwort

0

Also endete ich mit (nicht hübsch) Konstruktor Injektion. Wenn Sie einen besseren Weg haben, einschließlich vielleicht einen völlig anderen Ansatz zum Testen und Schreiben von Asynchron-Fabriken, bitte teilen, ich werde gerne akzeptieren, dass

// tested class 
import B_Import from './b'; 
import C_Import from './c'; 

let B = B_Import; 
let C = C_Import; 
export function mock(B_Mock, C_Mock) { 
    B = B_Mock || B_Import; 
    C = C_Mock || C_Import; 
} 

export default class A { 
    someFunction() { 
    let instanceB = new B(); 
    return instanceB.doSomething() 
     .then(() => this.doSomethingElse()) 
     .then((data) => { 
     // async context, other tests will start before this. 
     let instanceC = new C(data); 
     }); 
    } 
} 


// test 
import A, { mock as mockB } from './a'; 

setupMockB = (cfg, mockCallback) => { 
    const ClassMock = class { 
     constructor() { 
      // use cfg 
     } 
     doSomething() {} 
    } 
    if(mockCallback) {mockCallback(ClassMock.prototype);} 
    mockB(ClassMock, null) 
} 

describe('test',() => { 
    afterEach(() => mockB()) 
    it('case1',() => { 
    a = new A(); 
    setupMockB(cfg1, (mb) => sinon.stub(mb, 'doSomething').resolves()) 
    return a.someFunction().then(() => { /* asserts1 */ }); 
    }) 
    it('case2',() => { 
    a = new A(); 
    setupMockB(cfg2, (mb) => sinon.stub(mb, 'doSomething').rejects()) 
    return a.someFunction().then(() => { /* asserts2 */ }); 
    }) 
}) 
Verwandte Themen