I'm getting a timeout error when I try to send the contract to Ganache. My code is as follows,
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const {interface,bytecode} = require('../compile');
let accounts;
let inbox;
beforeEach(async() => {
accounts = await web3.eth.getAccounts();
inbox = await new web3.eth.Contract(JSON.parse(interface))
.deploy({data: bytecode,arguments:['Hi There !'] })
.send({from: accounts[0], gas:'1000000'});
});
describe("inbox", () => {
it('deploys a contract', () => {
console.log(inbox);
})
})
When I comment out the send method (provided below), the program runs without any issues. However, adding it back introduces the timeout error. No matter howmuch time I assign for mocha timeout, I still get the same error.
.send({from: accounts[0], gas:'1000000'});
There are similar posts regarding timeout such as listed below,
Error: Timeout of 2000ms exceeded. For async tests and hooks. Unit test with mocha and chai
Unit test error with mocha and chai Timeout of 2000ms exceeded. For async tests and hooks
Mocha testing with promises: Error: Timeout of 2000ms exceeded
Mocha exceeding 2000ms timeout when returning a promise
None of the above solutions worked for me (mostly talking about increasing the timeout). Additionally, I downgraded web3 library as proposed in a different forum. However, it didn't work either.
You can find the exact issue posted by someone else at a different forum. Apparently, that question has not received any potential answers as well.
I installed truffle v5.0.24 and started working on the truffle console which solved all the issues.
Related
I would like to know whether it is safe to make HTTP(S) requests during the Init phase of a NodeJS Lambda function. In particular, I would like to make calls to AWS SSM GetParameter using #aws-sdk/client-ssm or AWS KMS Decrypt using #aws-sdk/client-kms to load secrets that will be used within the handler.
I have found one example online of someone creating a Promise outside of the handler and then awaiting it within the handler (Async Initialisation of a Lambda Handler), but I haven’t seen this approach endorsed in the official Lambda sample applications. None of the official examples do any work outside of the handler.
According to AWS Lambda execution environment: Lambda execution environment lifecycle, “Lambda freezes the execution environment when the runtime and each extension have completed and there are no pending events.” AWS Lambda Runtime API: Next invocation elaborates on the http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next endpoint, “Do not set a timeout on the GET call. Between when Lambda bootstraps the runtime and when the runtime has an event to return, the runtime process may be frozen for several seconds.” I take this to mean that Lambda will signal the process with SIGSTOP at the time of the next call if Provisioned Concurrency is enabled as well as between requests.
In addition, when I look at lambcli’s lambda sources (docker run -it --rm lambci/lambda:build-nodejs12.x cat /var/runtime/Runtime.js), I see that scheduleIteration calls setImmediate(() => this.handleOnce()…) which calls this.client.nextInvocation so I don’t see a way to delay the nextInvocation call.
Questions:
In the Lambda nodejs runtime, is it possible to perform a HTTP request and await its response entirely within the Function init phase?
If you make a request outside of the handler, will the server time out the connection, resulting in Connection Closed errors when the handler awaits the response?
Is there a better recommended way to perform one-time initialization of secrets?
While I'm not able to fully answer all of your questions, I found this blog post that describes a possible solution: https://barker.tech/aws-lambda-nodejs-async-init-88b5c24af567
So in the end, the answers would be:
Yes, it is possible - see linked blog post.
Yes, it will time out. At least, this is what I experienced an issue when I tried to establish a MongoDB-connection outside the function handler with Provisioned Concurrency configured.
I can't really help you with that one...
AWS recently added top level await support in node14 and newer lambdas: https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda/ . Using this you can simply make the init phase wait by using top level await like so:
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
console.log("start init");
await sleep(1000);
console.log("end init");
export const handler = async (event) => {
return {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
};
This works great if you are using ES modules. If for some reason you are stuck using commonjs (e.g. because your tooling like jest or ts-node doesn't yet fully support ES modules) then you can make your commonjs module look like an es module by making it export a Promise that waits on your initialization rather than exporting an object. Like so:
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
const main = async () => {
console.log("start init");
await sleep(1000);
console.log("end init");
const handler = async (event) => {
return {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
};
return { handler };
};
# note we aren't exporting main here, but rather the result
# of calling main() which is a promise resolving to {handler}:
module.exports = main();
Our test suite includes a bunch of tests that ensure that out form vee-validate messages are displaying. To do this we create a wrapper:
wrapper = shallowMount(SetPasswordForm, {
i18n,
sync: false,
localVue,
propsData: {
user: {
emailAddress: 'afake#email.com'
}
}
})
Set the data, click submit, and then await flushPromises to give vee-validate time for the warnings to show.
it('renders minimum length error and has no match error', async () => {
wrapper.setData({
password: 'sut',
confirmPassword: 'sut'
})
wrapper.find('button.primary-action-btn').trigger('click')
await flushPromises()
expect(wrapper.text()).to.include('This field has a min length of 10')
expect(wrapper.vm.errors.count()).to.equal(2)
})
However, we do this a lot throughout the application and every test that uses await flushPromises takes increasingly long to run. I'm talking an increase of about 100ms every test. We have 180 unit tests and the final tests in the suite take up to 3 seconds to run.
Is that normal? I don't think it is. Are we calling await flushPromises too often? Is this a problem with our test suite or is it actually a memory leak?
Edit:
Github issue: https://github.com/baianat/vee-validate/issues/2095
I am currently learning Solidity and trying to build a simple contract. I am also trying to use the Mocha framework to test the smart contract before deploying. The test code is per below:
const assert = require("assert");
const ganache = require("ganache-cli");
const Web3 = require("web3");
const { interface, bytecode } = require("../compile");
const provider = ganache.provider();
const web3 = new Web3(provider);
let accounts;
let inbox;
beforeEach(async () => {
// Get a list of all accounts
accounts = await web3.eth.getAccounts();
// Use one of those accounts to deploy the contract
inbox = await new web3.eth.Contract(JSON.parse(interface))
.deploy({
data: bytecode,
arguments: ["Hi there!"]
})
.send({
from: accounts[0],
gas: "1000000"
});
});
describe("Inbox", () => {
it("deploys a contract", () => {
console.log(inbox);
});
});
The test fails and timeouts:
> mocha
Inbox
1) "before each" hook for "deploys a contract"
0 passing (2s)
1 failing
1) "before each" hook for "deploys a contract":
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
I noticed that the test passes if I comment out the send() argument:
// .send({
// from: accounts[0],
// gas: "1000000"
// });
So the issue must be with using this method. Not sure if it is an async issue.
I solved this by downgrading web3 to 1.0.0-beta.37. Seems like version 1.0.0-beta.51 is buggy.
I am learning sinon currently. My codes:
const bluebird = require('bluebird');
const sinon = require('sinon');
const sinonTest = require('sinon-test')(sinon);
sinon.test = sinonTest;
describe('xxx', function _test() {
this.timeout(2000);
it('should', sinon.test(function() {
return new bluebird.Promise( (resolve, reject) => {
try {
console.log('123');
resolve();
} catch ( err ) {
reject(err);
};
})
.then( () => console.log('456') )
.delay(100)
.then( () => console.log('789') )
.then(function() {
})
}));
});
output:
xxx
123
456
Why the above code times out and stuck in delay? Thanks
UPDATE
const bluebird = require('bluebird');
const sinon = require('sinon');
const sinonTest = require('sinon-test')(sinon);
sinon.test = sinonTest;
describe('xxx', function _test() {
this.timeout(2000);
it('should', sinon.test(function() {
return bluebird
.delay(100)
.then( () => console.log('789') );
}));
});
Output:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves
UPDATE
Thanks #Louis. Setting useFakeTimers works fine.
But I am just confused. Why in my project, there are no problems with the existing tests where useFakeTimers set to true by default? If useFakeTimers set true, promise delay cannot be used in sinonTest()?
By the way, I had this problem when upgrading sinon from 1.17.6 to 2.4.1.
Thanks
By default the sandboxes that Sinon creates have their configuration set so that the sandbox configuration option useFakeTimers is true. (Search for defaultConfig in this documentation page.)
This means that while the sandbox is in effect, the clock appears to be stopped, and Bluebird's delay never resolves. You tell sinon-test to create sandboxes without fake timers by passing a 2nd parameter when you configure it. This 2nd parameter is actually a configuration object for Sinon sandboxes:
const sinonTest = require('sinon-test')(sinon,
{ useFakeTimers: false });
I have not tried it, but from eyeballing the code, it looks like you could use multiple configurations at the same time if you need some tests to use fake timers and some to not use fake timers:
const sinonTest = require('sinon-test');
const wrapper = sinonTest(sinon, { useFakeTimers: false });
const wrapperWithTimers = sinonTest(sinon);
You just need to use the right wrapper for the needs of the test.
You added the question:
But I am just confused. Why in my project, there are no problems with the existing tests where useFakeTimers set to true by default? If useFakeTimers set true, promise delay cannot be used in sinonTest()?
By default useFakeTimers is true, but that won't cause a problem unless you have code that depends on the clock moving forward to work properly. I have many test suites where I use sandboxes and where I did not take care to turn off the fake timers and they work fine. Fake timers do not generally prevent asynchronous functions from running. If you do fs.readFile while the sandbox is in effect, for instance, it should work just fine. It just affects functions that depend on the clock, like setTimeout, setInterval and Date.
Bluebird's delay method is affected because it calls setTimeout.
I'm writing unit tests using Mocha and shouldjs, and bluebird.
According to the documentation (http://shouldjs.github.io/#assertion-finally) I should be able to return a Promise, and get it tested.
It is being run, but not tested. An assertion is thrown, but the test seemingly passes
Here is my code. It's pretty well straight out of the shouldjs docs:
'use strict';
require('should');
var Promise = require('bluebird');
describe('demo should error', function () {
it('I should fail - but Im not', function () {
var prm = new Promise(function(resolve, reject) { resolve(10); });
return prm.should.be.finally.equal(9);
});
});
When I run this in mocha, I get the following:
>>> mocha tests/demo.js
(node) child_process: options.customFds option is deprecated. Use options.stdio instead.
․Unhandled rejection AssertionError: expected 10 to be 9
at Assertion.fail (/Users/andrew/projects/DELETE_ME/2016-02-07/node_modules/should/lib/assertion.js:91:17)
at Assertion.Object.defineProperty.value (/Users/andrew/projects/DELETE_ME/2016-02-07/node_modules/should/lib/assertion.js:163:19)
...
1 passing (14ms)
So an exception is thrown, but the test seemingly passes.
I also get a false positive when I use native Promise, not bluebird, but the stack trace isn't shown.
Any help gratefully received...
I was using an outdated Mocha...
npm i -g mocha
Did the trick