dynamodb-toolbox icon indicating copy to clipboard operation
dynamodb-toolbox copied to clipboard

Add integration tests with dynalite

Open jeremydaly opened this issue 6 years ago • 19 comments

The current test suite has over 100 tests, but they mostly verify expected parameters. It would be helpful (and safer) to test them against a DynamoDB instance. A cloud version would be best, but since we want TravisCI to run the tests for us, we should be able to use DynamoDB Local.

jeremydaly avatar Dec 01 '19 02:12 jeremydaly

Let me know if there are any blockers to using dynalite instead (which should be easier to launch/install cause it's just npm/JS). I haven't really put much love into it in the last couple of years, but if there are some small features that are missing, I'd be happy to see if I can implement them.

mhart avatar Dec 01 '19 21:12 mhart

Actually, it was the first thing I looked at. 😉

But then I read your note that said DynamoDB Local is "actually pretty good, and considering it's now probably used by countless AWS devs, it'll probably be well supported going forward."

That made me think maybe DDB Local would be a better choice, but I'm happy to use dynalite if it supports (or could support) the funky things I'm doing.

jeremydaly avatar Dec 02 '19 05:12 jeremydaly

@mhart,

Added a sample test using dynalite (see 1375fe7). I had to use the "in memory" option, otherwise I was getting the occasional "Resource In Use" error from LevelDB.

I'm going to shift my efforts to some of the larger refactors before I build any additional tests, but would love to know if you think my implementation makes sense. I was thinking about starting this from the command line during the CI process, but then figured it would be easier to test locally if it just used the JS version.

I am going to need transaction support soon, but I can mock that until dynalite supports it.

Thanks, Jeremy

jeremydaly avatar Dec 09 '19 19:12 jeremydaly

Looks good to me! I'd love to know a little more about these "Resource In Use" errors though. Were they LevelDB errors, or DynamoDB-like errors from dynalite?

mhart avatar Dec 09 '19 19:12 mhart

They didn't appear to be DynamoDB-like. It was happening when I would put and then get right away. I think if you fork the project and just add a path to the dynalite config, you could replicate it. Didn't happen all the time, so it seems like it might be a locking issue.

jeremydaly avatar Dec 09 '19 20:12 jeremydaly

Yeah, I (sometimes) test by setting that: https://github.com/mhart/dynalite/blob/master/test/helpers.js#L49

Running DYNALITE_PATH=./dynalite npm test works fine though. Might be that I just don't have the right sort of tests to reproduce? Seems unlikely though.

mhart avatar Dec 09 '19 20:12 mhart

Strange. In memory works just fine, so not a big deal. Any benefits to using LevelDB?

jeremydaly avatar Dec 09 '19 20:12 jeremydaly

No, none at all unless you want persistence – for tests I'd definitely recommend in-memory

mhart avatar Dec 09 '19 20:12 mhart

Just wanted to make sure it wasn't a ResourceInUseException you were running into. Cause that's legit

mhart avatar Dec 09 '19 20:12 mhart

That's what it was!

jeremydaly avatar Dec 09 '19 20:12 jeremydaly

So that's a legit DynamoDB error that happens if you're trying to delete a table that's still being created or something similar to that.

You should wait for the tables to stop being in a CREATING (or DELETING) state before proceeding.

Adding this logic also means you can test against a real DynamoDB table.

mhart avatar Dec 09 '19 20:12 mhart

Ah, that makes sense. I had set the createTableMs and deleteTableMs to 0, but maybe there was still some blocking with LevelDB. Could also be because I was running the tests too quickly. I appreciate the feedback. Thanks again!

jeremydaly avatar Dec 09 '19 20:12 jeremydaly

Yeah, I use a setTimeout – so there's still a window before the next process tick.

I could special case a value of zero I guess. I just wanted ppl to be aware that you can't actually create a table that's in an ACTIVE state.

mhart avatar Dec 09 '19 20:12 mhart

I can definitely add a setTimeout after table creation. I will most likely be using a real table to do some local tests, so it would be good to build in that support. How long do you reckon I need? (and yes, I just used the word 'reckon')

jeremydaly avatar Dec 09 '19 20:12 jeremydaly

Oh, I'd poll for the state – it can take a variable amount of time with production DDB. I poll every second in my tests, but you could make it quicker if you wanted. https://github.com/mhart/dynalite/blob/master/test/helpers.js#L231-L239

mhart avatar Dec 09 '19 21:12 mhart

Super helpful! Thanks!

jeremydaly avatar Dec 09 '19 21:12 jeremydaly

Just a question. Wouldn't it be better to mock DocumentClient? It doesn't seem like Toolbox needs to know anything about the DB itself. Just that Toolbox makes the correct request with the correct options. This would also reduce the complexity of your test suite.

mikestopcontinues avatar Jul 02 '20 16:07 mikestopcontinues

I'm using Dynalite with https://www.npmjs.com/package/jest-dynalite. Not sure if that's taking care of the setTimeout stuff for me, but I haven't hit an issue with the table not being ready.

brettstack avatar Jan 04 '21 00:01 brettstack

Just a question. Wouldn't it be better to mock DocumentClient? It doesn't seem like Toolbox needs to know anything about the DB itself. Just that Toolbox makes the correct request with the correct options. This would also reduce the complexity of your test suite.

This. I have used the AWS SDK mocks in the past to test my code without the need to have a database.

darbio avatar Jan 05 '21 19:01 darbio

I've added a task on our board regarding integration tests, I'll be closing this issue for now.

naorpeled avatar Nov 21 '22 09:11 naorpeled