2016-10-31 4 views
2

Я искал в Интернете какое-то время, и мне еще предстоит найти ответ на этот вопрос.Единичные тесты: Тестирование внутреннего обещания

Допустим, мы тестируем следующее:

function p() { 
    return Promise.resolve(1); 
} 

class Sample { 
    constructor() { 
     this.stuff = 2; 
    } 

    sample() { 
     p().then((data) => { 
      this.stuff = data; 
     }); 

     //more stuff 
    } 
} 

module.exports = {Sample}; 

Как мы могли убедиться, что, в конце концов this.stuff заполняется без возвращения сказал обещание?

Это то, что я не был в состоянии сделать до сих пор:

let expect = require('chai').expect; 
let sinon = require('sinon'); 

let Sample = require('./source.js').Sample; 

describe('stuff', function() { 
    it('test2', function() { 
     let sample = new Sample(); 

     return Promise.resolve(sample.sample()) 
      .then(() => { 
       expect(sample.stuff).to.be.eql(2); 
      }); 
    }); 
}); 

В которой каждый then получает следующий тик (если мы имели несколько then с в нашей выборке мы также должны множественным then с в нашем тесте).

(И прежде чем вы говорите process.nextTick, я хочу, чтобы это запустить в браузере с кармой-мокко)

Спасибо заранее!

+0

Вы смотрели на chai-as-обещали? – kenhowardpdx

+0

@kenhowardpdx Я сделал, но если бы я правильно понял, это сработало бы, если бы у меня было внутреннее обещание. Но, читая документацию по chai-as-обещанному, возможно, дал мне идею. – Atekon

ответ

0

Это может быть легко протестировано, если код был изменен, чтобы обеспечить тестируемость.

Один из способов сделать это - взять необязательный интерфейс p для создания объекта. Значение может по умолчанию соответствовать вашему p, но позволит провести тест для создания поддельного объекта и убедиться, что ваш Sample работает на нем правильно.

function p() { 
    return Promise.resolve(1); 
} 

class Sample { 
    constructor(pFn) { 
     this.stuff = 2; 
     this.p = pFn || p; 
    } 

    sample() { 
     this.p().then((data) => { 
      this.stuff = data; 
     }); 

     //more stuff 
    } 
} 

Это позволит вам предоставить объект, похожий на обещание, для вашего модульного теста, который выполняется синхронно.

+0

Итак, вы говорите, что в тесте мне нужно будет сделать что-то вроде 'let sample = new Sample ({then:() => 2});'? Это немного сложновато, но я думаю, что это может сработать (возможно, оно не масштабируется в крупномасштабном проекте) – Atekon

+0

@Atekon да тест будет отвечать (и способен) настраивать любой тип объекта, который необходим, чтобы проверить, что ему нужно к. – dm03514

+0

'' ' pMock = function() { return { then: function (fn) { return fn (2); }} } пусть образец = новый образец (pMock); ' Он делает работу, но uhmmm это не cleaniest код никогда XD – Atekon

0

Один из способов - периодически проверять установленное значение.

it('test2', function(done) { 
    let sample = new Sample(); 
    let assert = function() { 
     if(sample.stuff === 2) { 
      done(); 
     } else { 
      setTimeout(assert, 0); 
     } 
    }; 

    sample.sample(); 
    assert(); 
}); 

Это не самый красивый и не даст лучшего сообщения об ошибке при сбое, но это сработает. Если sample.stuff не установлен на 2 в течение пары секунд (думаю, 3 секунды по умолчанию), то тест завершится неудачно, потому что done() не был вызван вовремя.


Другим возможным вариантом является тест заменить stuff с легавой. Затем вы можете установить expect().

it('test2', function(done) { 
    let sample = new Sample(); 
    Object.defineProperty(sample, 'stuff', { set: function (value) { 
     expect(value).to.be.eql(2); 
     done(); 
    }}); 

    sample.sample(); 
}); 
+0

Да, я предполагаю, что я мог бы сделать это, но я искал что-то симпатичный XD – Atekon

+0

@Atekon - понятно. Я добавил второе возможное решение. Я не пробовал, но думаю, что это может сработать. Возможно, вам понадобится добавить геттер тоже в зависимости от остальной части вашего кода. – CodingWithSpike

+0

Не думал об этом (это отличная идея), но сеттер никогда не вызывается (поскольку тогда он никогда не выполняется). – Atekon

Смежные вопросы