2024-10-06 02:35:50 +00:00
|
|
|
import 'package:test/test.dart';
|
|
|
|
import 'package:mockito/annotations.dart';
|
|
|
|
import 'package:mockito/mockito.dart';
|
|
|
|
import 'package:angel3_container/angel3_container.dart';
|
|
|
|
import 'package:angel3_event_bus/event_bus.dart';
|
|
|
|
import 'package:angel3_mq/mq.dart';
|
|
|
|
import 'package:angel3_queue/src/queue.dart';
|
2024-10-06 04:06:00 +00:00
|
|
|
|
2024-10-06 05:07:25 +00:00
|
|
|
import 'package:angel3_queue/src/job_queueing_event.dart';
|
|
|
|
import 'package:angel3_queue/src/job_queued_event.dart';
|
2024-10-06 04:06:00 +00:00
|
|
|
import 'package:angel3_queue/src/should_queue_after_commit.dart';
|
2024-10-06 02:43:53 +00:00
|
|
|
//import 'package:angel3_queue/src/invalid_payload_exception.dart';
|
2024-10-06 02:35:50 +00:00
|
|
|
import 'queue_test.mocks.dart';
|
|
|
|
|
2024-10-06 05:07:25 +00:00
|
|
|
@GenerateMocks([Container, EventBus, MQClient, TransactionManager])
|
2024-10-06 02:35:50 +00:00
|
|
|
void main() {
|
|
|
|
late MockContainer container;
|
2024-10-06 05:07:25 +00:00
|
|
|
late MockEventBus eventBus;
|
2024-10-06 02:35:50 +00:00
|
|
|
late MockMQClient mq;
|
|
|
|
late TestQueue queue;
|
|
|
|
|
|
|
|
setUpAll(() {
|
2024-10-06 05:07:25 +00:00
|
|
|
provideDummy<EventBus>(MockEventBus());
|
2024-10-06 02:35:50 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
setUp(() {
|
|
|
|
container = MockContainer();
|
2024-10-06 05:07:25 +00:00
|
|
|
eventBus = MockEventBus();
|
2024-10-06 02:35:50 +00:00
|
|
|
mq = MockMQClient();
|
|
|
|
queue = TestQueue(container, eventBus, mq);
|
|
|
|
|
2024-10-06 04:06:00 +00:00
|
|
|
// Inject the other mocks into the queue
|
|
|
|
// queue.container = container;
|
|
|
|
// queue.mq = mq;
|
|
|
|
|
2024-10-06 02:35:50 +00:00
|
|
|
when(container.has<EventBus>()).thenReturn(true);
|
|
|
|
when(container.has<TransactionManager>()).thenReturn(false);
|
|
|
|
when(container.make<EventBus>()).thenReturn(eventBus);
|
2024-10-06 05:07:25 +00:00
|
|
|
|
|
|
|
// Setup for EventBus mock
|
|
|
|
when(eventBus.fire(any)).thenAnswer((_) => Future<void>.value());
|
|
|
|
|
2024-10-06 06:46:09 +00:00
|
|
|
// Setup for MQClient mock
|
|
|
|
when(mq.sendMessage(
|
|
|
|
message: anyNamed('message'),
|
|
|
|
exchangeName: anyNamed('exchangeName'),
|
|
|
|
routingKey: anyNamed('routingKey'),
|
|
|
|
)).thenAnswer((_) {
|
|
|
|
print("Debug: Mock sendMessage called");
|
|
|
|
// Notice we're not returning anything here
|
|
|
|
});
|
2024-10-06 02:35:50 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
test('pushOn calls push with correct arguments', () async {
|
|
|
|
final result = await queue.pushOn('test_queue', 'test_job', 'test_data');
|
|
|
|
expect(result, equals('pushed'));
|
|
|
|
});
|
|
|
|
|
|
|
|
test('laterOn calls later with correct arguments', () async {
|
|
|
|
final result = await queue.laterOn(
|
|
|
|
'test_queue', Duration(minutes: 5), 'test_job', 'test_data');
|
|
|
|
expect(result, equals('pushed later'));
|
|
|
|
});
|
2024-10-06 02:43:53 +00:00
|
|
|
|
|
|
|
test('bulk pushes multiple jobs', () async {
|
|
|
|
await queue.bulk(['job1', 'job2', 'job3'], 'test_data', 'test_queue');
|
|
|
|
expect(queue.pushedJobs.length, equals(3));
|
|
|
|
expect(queue.pushedJobs, containsAll(['job1', 'job2', 'job3']));
|
|
|
|
});
|
|
|
|
|
|
|
|
test('createPayload throws InvalidPayloadException for invalid job', () {
|
|
|
|
expect(() => queue.createPayload({}, 'test_queue'),
|
|
|
|
throwsA(isA<InvalidPayloadException>()));
|
|
|
|
});
|
2024-10-06 04:06:00 +00:00
|
|
|
test('shouldDispatchAfterCommit returns correct value', () {
|
|
|
|
expect(
|
|
|
|
queue.shouldDispatchAfterCommit(MockShouldQueueAfterCommit()), isTrue);
|
|
|
|
expect(queue.shouldDispatchAfterCommit({}), isFalse);
|
|
|
|
|
|
|
|
queue.dispatchAfterCommit = true;
|
|
|
|
expect(queue.shouldDispatchAfterCommit({}), isTrue);
|
|
|
|
});
|
2024-10-06 05:07:25 +00:00
|
|
|
|
|
|
|
test('enqueueUsing publishes message and fires events', () async {
|
|
|
|
when(container.has<TransactionManager>()).thenReturn(false);
|
|
|
|
|
2024-10-06 06:46:09 +00:00
|
|
|
print("Debug: Before enqueueUsing");
|
2024-10-06 05:07:25 +00:00
|
|
|
await queue.enqueueUsing(
|
|
|
|
'test_job',
|
|
|
|
'test_payload',
|
|
|
|
'test_queue',
|
|
|
|
null,
|
|
|
|
(payload, queue, delay) async => 'job_id',
|
|
|
|
);
|
2024-10-06 06:46:09 +00:00
|
|
|
print("Debug: After enqueueUsing");
|
|
|
|
|
|
|
|
// Verify all method calls in order
|
|
|
|
verifyInOrder([
|
|
|
|
eventBus.fire(argThat(isA<JobQueueingEvent>())),
|
|
|
|
eventBus.fire(argThat(isA<JobQueuedEvent>())),
|
|
|
|
mq.sendMessage(
|
|
|
|
message: anyNamed('message'),
|
|
|
|
exchangeName: anyNamed('exchangeName'),
|
|
|
|
routingKey: anyNamed('routingKey'),
|
|
|
|
),
|
|
|
|
]);
|
|
|
|
|
|
|
|
// Print captured arguments for sendMessage
|
|
|
|
final sendMessageCall = verify(mq.sendMessage(
|
|
|
|
message: captureAnyNamed('message'),
|
|
|
|
exchangeName: captureAnyNamed('exchangeName'),
|
|
|
|
routingKey: captureAnyNamed('routingKey'),
|
|
|
|
));
|
|
|
|
|
|
|
|
if (sendMessageCall.captured.isNotEmpty) {
|
|
|
|
print("sendMessage was called with:");
|
|
|
|
print("message: ${sendMessageCall.captured[0]}");
|
|
|
|
print("exchangeName: ${sendMessageCall.captured[1]}");
|
|
|
|
print("routingKey: ${sendMessageCall.captured[2]}");
|
|
|
|
} else {
|
|
|
|
print("sendMessage was not called");
|
|
|
|
}
|
2024-10-06 05:07:25 +00:00
|
|
|
|
2024-10-06 06:46:09 +00:00
|
|
|
// Additional verifications
|
2024-10-06 05:07:25 +00:00
|
|
|
verify(eventBus.fire(any)).called(2);
|
|
|
|
verify(mq.sendMessage(
|
2024-10-06 06:46:09 +00:00
|
|
|
message: anyNamed('message'),
|
|
|
|
exchangeName: anyNamed('exchangeName'),
|
|
|
|
routingKey: anyNamed('routingKey'),
|
2024-10-06 05:07:25 +00:00
|
|
|
)).called(1);
|
|
|
|
});
|
2024-10-06 02:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class TestQueue extends Queue {
|
2024-10-06 02:43:53 +00:00
|
|
|
List<dynamic> pushedJobs = [];
|
|
|
|
|
2024-10-06 02:35:50 +00:00
|
|
|
TestQueue(Container container, EventBus eventBus, MQClient mq)
|
|
|
|
: super(container, eventBus, mq);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<dynamic> push(dynamic job, [dynamic data = '', String? queue]) async {
|
2024-10-06 02:43:53 +00:00
|
|
|
pushedJobs.add(job);
|
2024-10-06 02:35:50 +00:00
|
|
|
return 'pushed';
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<dynamic> later(Duration delay, dynamic job,
|
|
|
|
[dynamic data = '', String? queue]) async {
|
|
|
|
return 'pushed later';
|
|
|
|
}
|
2024-10-06 02:43:53 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
Future<String> createPayload(dynamic job, String queue,
|
|
|
|
[dynamic data = '']) async {
|
|
|
|
if (job is Map && job.isEmpty) {
|
|
|
|
throw InvalidPayloadException('Invalid job: empty map');
|
|
|
|
}
|
|
|
|
return 'valid payload';
|
|
|
|
}
|
2024-10-06 04:06:00 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
bool shouldDispatchAfterCommit(dynamic job) {
|
|
|
|
if (job is ShouldQueueAfterCommit) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return dispatchAfterCommit;
|
|
|
|
}
|
2024-10-06 02:35:50 +00:00
|
|
|
|
|
|
|
@override
|
2024-10-06 05:07:25 +00:00
|
|
|
Future<dynamic> enqueueUsing(
|
|
|
|
dynamic job,
|
|
|
|
String payload,
|
|
|
|
String? queue,
|
|
|
|
Duration? delay,
|
|
|
|
Future<dynamic> Function(String, String?, Duration?) callback,
|
|
|
|
) async {
|
2024-10-06 06:46:09 +00:00
|
|
|
eventBus.fire(JobQueueingEvent(connectionName, queue, job, payload, delay));
|
2024-10-06 05:07:25 +00:00
|
|
|
final result = await callback(payload, queue, delay);
|
2024-10-06 06:46:09 +00:00
|
|
|
eventBus.fire(
|
|
|
|
JobQueuedEvent(connectionName, queue, result, job, payload, delay));
|
2024-10-06 05:07:25 +00:00
|
|
|
|
2024-10-06 06:46:09 +00:00
|
|
|
print("Attempting to send message..."); // Debug print
|
2024-10-06 05:07:25 +00:00
|
|
|
mq.sendMessage(
|
|
|
|
message: Message(
|
|
|
|
id: 'test-id',
|
|
|
|
headers: {},
|
|
|
|
payload: payload,
|
|
|
|
timestamp: DateTime.now().toIso8601String(),
|
|
|
|
),
|
|
|
|
exchangeName: '',
|
|
|
|
routingKey: queue ?? 'default',
|
|
|
|
);
|
2024-10-06 06:46:09 +00:00
|
|
|
print("Message sent."); // Debug print
|
2024-10-06 05:07:25 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2024-10-06 02:35:50 +00:00
|
|
|
}
|
2024-10-06 02:43:53 +00:00
|
|
|
|
2024-10-06 05:07:25 +00:00
|
|
|
// class DummyEventBus implements EventBus {
|
|
|
|
// List<AppEvent> firedEvents = [];
|
|
|
|
|
|
|
|
// @override
|
|
|
|
// Future<void> fire(AppEvent event) async {
|
|
|
|
// firedEvents.add(event);
|
|
|
|
// }
|
|
|
|
|
|
|
|
// @override
|
|
|
|
// dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
|
|
|
|
// }
|
|
|
|
|
2024-10-06 02:43:53 +00:00
|
|
|
class InvalidPayloadException implements Exception {
|
|
|
|
final String message;
|
|
|
|
InvalidPayloadException(this.message);
|
|
|
|
@override
|
|
|
|
String toString() => 'InvalidPayloadException: $message';
|
|
|
|
}
|
2024-10-06 04:06:00 +00:00
|
|
|
|
|
|
|
class MockShouldQueueAfterCommit implements ShouldQueueAfterCommit {}
|