Как покрыть setInterval в случае модульного теста в JavaScript - PullRequest
0 голосов
/ 24 августа 2018

Привет, я пишу тестовый блок этой функции.Когда я запускаю эту функцию из примера модульного теста, она охватывает все операторы, но setInterval полные строки не охватываются.

Кто-нибудь знает, как покрыть ее в javascript?Я использую мокко.

const open = async function (config) {

    ...... set of lines..

    let retryIn = setInterval(async () => {
        try {
            client = await connect(config);
            clearInterval(retryIn);
            return client;
        } catch (err) {
           //error
        }
    }, 20000);

};

Я просто называю это так

it("###test", async () => {
        open(config);
    });
});

Ответы [ 3 ]

0 голосов
/ 24 августа 2018

Просто заверните в Promise

const open = async function (config) {
    ...... set of lines..
    return new Promise((resolve, reject) => {
      let retryIn = setInterval(async () => {
        client = await connect(asConfigParam);
        clearInterval(retryIn);
        return client;
      }, 20000);
      return resolve(retryIn);
    });
};


it("###test", async () => {
        const result = await open(config);
        console.log('result', result)
});
0 голосов
/ 24 августа 2018

Прежде всего, вы никогда не должны использовать setInterval в том случае, если вы хотите повторить задачу, которая не удалась.Вместо этого следует использовать setTimeout.

Кроме того, вы не можете вернуть значение из классической базовой функции обратного вызова, такой как setInterval или setTimeout.Таким образом, в его текущей форме обещание, возвращаемое при вызове open, будет разрешено до установления любого соединения.

С помощью await / async вы можете создать простую и понятную настройку для такой ситуации:

function wait(seconds) {
  return new Promise((resolve, _) => setTimeout(resolve, seconds))
}

async function connect() {
  throw new Error('failed')
}

async function open(config) {
  let client;

  while (client === undefined /* || retries > maxRetries*/ ) {
    try {
      client = await connect(config);
    } catch (err) {
      // if connection failed due to an error, wait n seconds and retry
      console.log('failed wait 2 seconds for reconnect');
      await wait(2000)
      // ++retries
    }
  }


  if (!client) {
    throw new Error('connection failed due to max number of retries reached.')
  }
  
  return client
}


async function main() {
  let connection = await open()
}

main().catch(err => console.log(err))

Вы можете расширить этот фрагмент, добавив предел повторных попыток.См. Комментарии для приблизительного представления о том, как этого можно достичь.

Чтобы протестировать приведенный выше код, вы должны написать:

it("###test", function() {
  return open(config);
});
0 голосов
/ 24 августа 2018

Кто-то опубликовал ответ о фальшивых таймерах, а затем удалил его. Ответ был правильным, поэтому я снова отправил сообщение.

Вы можете использовать sinonjs для создания фальшивых таймеров

Ложные таймеры - это синхронные реализации setTimeout и друзей, с которыми Sinon.JS может перезаписывать глобальные функции, чтобы вам было проще тестировать код, используя их

Но из вашего кода,кажется, вы пытаетесь проверить асинхронный код, в Мокко, это может быть достигнуто следующим образом

describe('somthing', () => {
  it('the result is 2', async () => {
    const x = await add(1, 1)
    expect(x).to.equal(4);
  });
});

с чем-то ближе к вашему коду

async function open() {

  return new Promise((resolve, reject) => {

    setTimeout(() => {
      resolve('done')
    }, 1000);
  });
};

describe('somthing', () => {
  it('###test', async () => {
    const x = await open()
    chai.expect(x).to.equal("done");
  });
});
...