import 'package:drift/drift.dart'; import 'package:mockito/mockito.dart'; class MockExecutor extends Mock implements QueryExecutor { late final MockTransactionExecutor transactions = MockTransactionExecutor(); late final MockExecutor exclusive = this; final OpeningDetails? openingDetails; bool opened = false; MockExecutor([this.openingDetails]) { when(dialect).thenReturn(SqlDialect.sqlite); when(runSelect(any, any)).thenAnswer((_) { assert(opened); return Future.value([]); }); when(runUpdate(any, any)).thenAnswer((_) { assert(opened); return Future.value(0); }); when(runDelete(any, any)).thenAnswer((_) { assert(opened); return Future.value(0); }); when(runInsert(any, any)).thenAnswer((_) { assert(opened); return Future.value(0); }); when(runCustom(any, any)).thenAnswer((_) { assert(opened); return Future.value(); }); when(runBatched(any)).thenAnswer((_) { assert(opened); return Future.value(); }); when(ensureOpen(any)).thenAnswer((i) async { if (!opened && openingDetails != null) { opened = true; await (i.positionalArguments.single as QueryExecutorUser) .beforeOpen(this, openingDetails!); } opened = true; return true; }); when(close()).thenAnswer((_) async { opened = false; }); } @override SqlDialect get dialect => _nsm(Invocation.getter(#dialect), SqlDialect.sqlite); @override Future ensureOpen(QueryExecutorUser? user) => _nsm(Invocation.method(#ensureOpen, [user]), Future.value(true)); @override Future>> runSelect( String? statement, List? args) => _nsm(Invocation.method(#runSelect, [statement, args]), Future.value(>[])); @override Future runInsert(String? statement, List? args) => _nsm(Invocation.method(#runInsert, [statement, args]), Future.value(0)); @override Future runUpdate(String? statement, List? args) => _nsm(Invocation.method(#runUpdate, [statement, args]), Future.value(0)); @override Future runDelete(String? statement, List? args) => _nsm(Invocation.method(#runDelete, [statement, args]), Future.value(0)); @override Future runCustom(String? statement, [List? args]) => _nsm( Invocation.method(#runCustom, [statement, args]), Future.value(null)); @override Future runBatched(BatchedStatements? statements) => _nsm(Invocation.method(#runBatched, [statements]), Future.value(null)); @override TransactionExecutor beginTransaction() => _nsm(Invocation.method(#beginTransaction, []), transactions) ?? transactions; @override QueryExecutor beginExclusive() => _nsm(Invocation.method(#beginExclusive, []), exclusive) ?? exclusive; @override Future close() => _nsm(Invocation.method(#close, []), Future.value(null)); } class MockTransactionExecutor extends MockExecutor implements TransactionExecutor { MockTransactionExecutor() { when(supportsNestedTransactions).thenReturn(true); when(send()).thenAnswer((_) => Future.value(null)); when(rollback()).thenAnswer((_) => Future.value(null)); } @override bool get supportsNestedTransactions { return _nsm(Invocation.getter(#supportsNestedTransactions), true); } @override Future send() { return _nsm(Invocation.method(#send, []), Future.value(null)); } @override Future rollback() => _nsm(Invocation.method(#rollback, []), Future.value(null)); } extension on Mock { T _nsm(Invocation invocation, Object? returnValue) { return noSuchMethod(invocation, returnValue: returnValue) as T; } }