I am using jasmine-node for doing unit testing. I did below code for mocking Date.now()
spyOn(Date, 'now').andReturn(1387636363717); //always return a fixed time
Then I tried to run jasmine-node spec/ but it stopped working with no output. I could not figure out what is the reason.
I have written a tiny test. It works just fine. Using jasmin-node in version 1.11.0.
Where is your Date.now function used then?
spyOn(Date, 'now').andReturn(1387636363717);
expect(Date.now()).toEqual(1387636363717);
The problem is that there is code in node runtime (timers.js) that calls Date.now() to mark the passage of time. If you have code that sets a timer (setTimeout) and that code is executed while not using jasmine.Clock, then you may find node.js is waiting for some time to pass before executing the next real timeout. Since this code appears to be called from outside javascript land, you can not rely
on the single-threaded nature of javascript to keep you safe from this. By putting a breakpoint on a .andCallFake on the Date.now spy, I was able to see that the execution of the spec was being indefinitely suspended waiting for a millisecond to pass.
This is a problem for me because we have a very large unit test suite and there are possibilities that setTimeout is called as a side effect of some other calls and jasmine.Clock is not used universally in every spec. Since this is the side effect of an optimization (note: 'too much overhead' in the comments), I would consider this to be a bug in node.js.
If you want to stop time for your tests:
Spy on Date.now inside your spec function (it function - not beforeEach). That way your spec won't be delayed (also explains why #marco.jantke did not see this issue).
if your code under test uses timers, use jasmine.Clock.
Related
asynchronous code such as setTimeout can only be run by using a browser; as the engine hands over the code to the browser till the time of execution comes. But in node, we have only an engine and no browser then how does setTimeout work on the node.
Asynchronous code is achieved using Promises, and optionally the async/await syntactic sugar.
Promises are implemented using raw JavaScript, and has nothing to do with whether the code is ran in the browser or not.
In your case you are referring to setTimeout. This function simply delays code execution by scheduling for the function to be called in JavaScript's event loop.
This is part of the core engine of JavaScript, and once again has nothing to do with the browser.
What makes you think that the browser makes any difference here?
Any implementation will have a mechanism in place for being able to wait for a certain amount of time to pass, this is not something special to a browser.
I use gitlab-ci to run my test suite, in one test I would like to simulate a
change of system date (like, going to the day after) in order to see if
everything works as expected, for example:
redis keys are deleted (TTL)
some files are written with a new 'run number' since the date as changed
date and time calculation are ok
...
How do I simulate change of system date/time for unit-testing purposes?
EDIT: since my code base is in Python, I found freezegun and python-libfatketime; the former can probably do the trick for my Python code, and the latter is more powerful since it is intercepting system calls so theoretically I can use it for testing redis TTL if I start redis after the patches are applied.
You can override gettimeofday and clock_gettime to return any time you want. However, that would not affect pthread waiting functions with timeouts.
How about not picking the Date from System and providing a Date from a Variable you can change by a Script ?
When writing a (unit) test suite, you need to clearly define the system under test and its boundaries. In this case your application belongs to the system under test, redis does not.
Things which do not belong to the system under test should be mocked. For python start here: https://docs.python.org/3/library/unittest.mock.html
I’ve recently started to figure out what event loop really is and that confused me a lot, seems like I don’t know how nodejs works..
I mean when program starts, gets loaded into memory - what’s next?
I can’t see a place inside event loop where all sync. Code executes (like for/ while cycles that’s computes something).. doesn’t that means that V8 executes JavaScript and starts event loop when needed?
If anybody can help and explain how nodejs runtime is functioning on the high level would be really great
I highly recommend reading this Asynchrony: Now & Later
and I'll quote some things that I've once read.
........
JS Engine know nothing about code being asynchronous,It only execute code at a time and finishes..no more no less
the JS host environment is the one who has an implementation of the event-loop concept where code that doesn't need to run now(in the future),is waiting(imagine a network call/ io call) to finish processing and get called (be added to the event-queue of the event-loop and then executed at a next tick)
At program start,I'm 100% sure but I think all code is added to the event-queue(the way how the event-loop is implemented) and it's processed as First in First out (FIFO) which means the earlier the code the first is executed,and while running if some code need to be stalled like a setTimeout or IO process or an Ajax call(which both need time) it's up to them to use for example a callback to call(here the callback is added to the event-queue) and it's the event-loop responsibility to execute these callback in order that they've reached in at a next future tick.
This is a general question about testing, but I will frame it in the context of Node.js. I'm not as concerned with a particular technology, but it may matter.
In my application, I have several modules that are called upon to do work when my web server receives a request. In the case of some of these modules, I close the request before I call upon them.
What is a good way to test that these modules are doing what they are supposed to do?
The advice here for RSpec is to mock out the work these modules are doing and just ensure that the appropriate methods are being called. This makes sense to me, but in Node.js, since my modules are not global, I don't think I cannot mock out functions without changing my program architecture so that every instance receives instances of objects that it needs1.
[1] This is a well known programming paradigm, but I cannot remember its name right now.
The other option I see is to use setTimeout and take my best guess at when these modules are done with their work.
Neither of these seems ideal.
Am I missing something? Are background processes not tested?
Since you are speaking of integration tests of these background components, a few strategies come to mind.
Take all the asynchronicity out of their operation for test mode. I'm imagining you have some sort of queueing process (that could be a faulty assumption), you toss work into the queue, and then your modules pick up that work and do their task. You could rework your test harness such that the test harness stands in as the queuing mechanism and you effectively get direct control over when the modules execute.
Refactor your modules to take some sort of next callback function. They would end up functioning a bit like Express's middleware layer or how async's each function works, but into each module you'd pass some callback that you call when that module's task is complete. Once all of the modules have reported in, then you can check the state of the program.
Exactly what you already suggested-- wait some amount of time, and if it still isn't done, consider that a failure. Mocha sort of does that, in that if a given test is over a definable threshold, then it's a failure. I don't like this way though, because if you add more tests, they all have to wait the same amount of time.
I am using Mocha to run some tests on my SnailMailAddressParser project from the command-line. Unfortunately only some tests are run before Mocha exits.
The test file is very straightforward. You can see the test file here: test/test.coffee
It seems there is a race condition somewhere. When I run npm test, it does one of two things:
Runs one test; or
Runs 34 tests, starting at address_tester.
Clearly I am doing something asynchronous that needs to be caught, but I am not quite sure what yet. In any case, I do not know how to tell Mocha to wait for any asynchronous items to be reaped (i.e. some sort of Mocha.wait_all, if that is even possible - perhaps I have to add' done() calls, but I didn't think that was necessary for synchronous testing - which I thought this might be).
I will experiment of course and post any answers I glean from my testing, but I would be grateful for any insight.
The answer was that
fs.readFile filename, "utf8", -> ...
was operating asynchronously. When I had tried using
fs.readFileSync filename, "utf8", -> ...
it was not working because I was still passing a callback instead of reading the return value.
I solved the problem by changing the callback to:
data = fs.readFileSync filename, "utf8"
as no asynchronous operation was now being called.