From 09d047a868088ea173915ced030ef6c6e5b08f03 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Sun, 10 Mar 2019 12:38:53 +0100 Subject: [PATCH] Tests for transactions --- README.md | 2 +- moor/lib/src/runtime/database.dart | 3 ++- moor/test/data/utils/mocks.dart | 23 ++++++++++++++++ moor/test/transactions_test.dart | 42 ++++++++++++++++++++++++++++++ moor_flutter/README.md | 2 +- 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 moor/test/transactions_test.dart diff --git a/README.md b/README.md index 55970577..c736fd12 100644 --- a/README.md +++ b/README.md @@ -319,8 +319,8 @@ supporting floating / fixed point numbers as well would be awesome - Validation - Table joins - Bulk inserts -- Transactions - Custom column constraints +- When inserts / updates fail, explain why that happened ### Interesting stuff that would be nice to have Implementing this will very likely result in backwards-incompatible changes. diff --git a/moor/lib/src/runtime/database.dart b/moor/lib/src/runtime/database.dart index d4dc85ec..951b8289 100644 --- a/moor/lib/src/runtime/database.dart +++ b/moor/lib/src/runtime/database.dart @@ -206,10 +206,11 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser /// [action] function. Future transaction(Future Function(QueryEngine transaction) action) async { final transaction = Transaction(this, executor.beginTransaction()); + try { await action(transaction); } finally { - await transaction?.complete(); + await transaction.complete(); } } } diff --git a/moor/test/data/utils/mocks.dart b/moor/test/data/utils/mocks.dart index c389a153..4043c10b 100644 --- a/moor/test/data/utils/mocks.dart +++ b/moor/test/data/utils/mocks.dart @@ -9,6 +9,9 @@ export 'package:mockito/mockito.dart'; typedef Future _EnsureOpenAction(QueryExecutor e); class MockExecutor extends Mock implements QueryExecutor { + + final MockTransactionExecutor transactions = MockTransactionExecutor(); + MockExecutor() { when(runSelect(any, any)).thenAnswer((_) => Future.value([])); when(runUpdate(any, any)).thenAnswer((_) => Future.value(0)); @@ -19,9 +22,29 @@ class MockExecutor extends Mock implements QueryExecutor { return action(this); }); + + when(beginTransaction()).thenAnswer((_) => transactions); } } +class MockTransactionExecutor extends Mock implements TransactionExecutor { + + MockTransactionExecutor() { + when(runSelect(any, any)).thenAnswer((_) => Future.value([])); + when(runUpdate(any, any)).thenAnswer((_) => Future.value(0)); + when(runDelete(any, any)).thenAnswer((_) => Future.value(0)); + when(runInsert(any, any)).thenAnswer((_) => Future.value(0)); + when(doWhenOpened(any)).thenAnswer((i) { + final action = i.positionalArguments.single as _EnsureOpenAction; + + return action(this); + }); + + when(send()).thenAnswer((_) => Future.value(null)); + } + +} + class MockStreamQueries extends Mock implements StreamQueryStore {} // used so that we can mock the SqlExecutor typedef diff --git a/moor/test/transactions_test.dart b/moor/test/transactions_test.dart new file mode 100644 index 00000000..41997889 --- /dev/null +++ b/moor/test/transactions_test.dart @@ -0,0 +1,42 @@ +import 'package:test_api/test_api.dart'; + +import 'data/tables/todos.dart'; +import 'data/utils/mocks.dart'; + +void main() { + TodoDb db; + MockExecutor executor; + MockStreamQueries streamQueries; + + setUp(() { + executor = MockExecutor(); + streamQueries = MockStreamQueries(); + db = TodoDb(executor)..streamQueries = streamQueries; + }); + + test("transactions don't allow creating streams", () { + expect(() async { + await db.transaction((t) { + t.select(db.users).watch(); + }); + }, throwsStateError); + + verify(executor.transactions.send()); + }); + + test('transactions notify about table udpates after completing', () async { + when(executor.transactions.runUpdate(any, any)).thenAnswer((_) => Future.value(2)); + + await db.transaction((t) async { + await t.update(db.users).write(User(name: 'Updated name')); + + // Even though we just wrote to users, this only happened inside the + // transaction, so the top level stream queries should not be updated. + verifyNever(streamQueries.handleTableUpdates(any)); + }); + + // After the transaction completes, the queries should be updated + verify(streamQueries.handleTableUpdates({'users'})); + verify(executor.transactions.send()); + }); +} \ No newline at end of file diff --git a/moor_flutter/README.md b/moor_flutter/README.md index 55970577..c736fd12 100644 --- a/moor_flutter/README.md +++ b/moor_flutter/README.md @@ -319,8 +319,8 @@ supporting floating / fixed point numbers as well would be awesome - Validation - Table joins - Bulk inserts -- Transactions - Custom column constraints +- When inserts / updates fail, explain why that happened ### Interesting stuff that would be nice to have Implementing this will very likely result in backwards-incompatible changes.