-
Notifications
You must be signed in to change notification settings - Fork 10
/
Testing.md
132 lines (96 loc) · 4.12 KB
/
Testing.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
Karafka provides a dedicated helper library for testing consumers and producers called [karafka-testing](https://github.com/karafka/karafka-testing).
## Installation
Add this gem to your Gemfile in the `test` group:
```ruby
group :test do
gem 'karafka-testing'
gem 'rspec'
end
```
and then in your `spec_helper.rb` file:
```ruby
require 'karafka/testing/rspec/helpers'
RSpec.configure do |config|
config.include Karafka::Testing::RSpec::Helpers
end
```
## Usage
Once included in your RSpec setup, this library will provide you with a special `#karafka` object that contains three methods that you can use within your specs:
- `#consumer_for` - creates a consumer instance for the desired topic. It **needs** to be set as the spec subject.
- `#produce` - "sends" message to the consumer instance.
- `#produced_messages` - contains all the messages "sent" to Kafka during spec execution.
**Note:** Messages sent using the `#produce` method and directly from `Karafka.producer` won't be sent to Kafka. They will be buffered and accessible in a per-spec buffer in case you want to test messages production.
Messages that target the topic built using the `karafka#consumer_for` method will additionally be delivered to the consumer you want to test.
### Testing messages consumption (consumers)
```ruby
RSpec.describe InlineBatchConsumer do
# This will create a consumer instance with all the settings defined for the given topic
subject(:consumer) { karafka.consumer_for('inline_batch_data') }
let(:nr1_value) { rand }
let(:nr2_value) { rand }
let(:sum) { nr1_value + nr2_value }
before do
# Sends first message to Karafka consumer
karafka.produce({ 'number' => nr1_value }.to_json)
# Sends second message to Karafka consumer
karafka.produce({ 'number' => nr2_value }.to_json, partition: 2)
allow(Karafka.logger).to receive(:info)
end
it 'expects to log a proper message' do
expect(Karafka.logger).to receive(:info).with("Sum of 2 elements equals to: #{sum}")
consumer.consume
end
end
```
If your consumers use `producer` to dispatch messages, you can check its operations as well:
```ruby
RSpec.describe InlineBatchConsumer do
subject(:consumer) { karafka.consumer_for(:inline_batch_data) }
before { karafka.produce({ 'number' => 1 }.to_json) }
it 'expects to dispatch async message to messages topic with value bigger by 1' do
consumer.consume
expect(karafka.produced_messages.last.payload).to eq({ number: 2 }.to_json)
end
end
```
### Testing messages production (producer)
When running RSpec, Karafka will not dispatch messages to Kafka using `Karafka.producer` but will buffer them internally.
This means you can check your application flow, making sure your logic acts as expected:
```ruby
# Example class in which there is a message production
class UsersBuilder
def create(user_details)
user = ::User.create!(user_details)
Karafka.producer.produce_sync(
topic: 'users_changes',
payload: { user_id: user.id, type: 'user.created' },
key: user.id.to_s
)
user
end
end
RSpec.describe InlineBatchConsumer do
let(:created_user) { UsersBuilder.new.create(user_details) }
before { created_user }
it { expect(karafka.produced_messages.size).to eq(1) }
it { expect(karafka.produced_messages.first[:topic]).to eq('user.created') }
it { expect(karafka.produced_messages.first[:key]).to eq(created_user.id.to_s) }
end
```
### Testing consumer groups and topics structure
Sometimes you may need to spec out your consumer groups and topics structure. To do so, simply access the ```Karafka::App.routes``` array and check everything you need. Here's an example of a Rspec spec that ensures a custom ```XmlDeserializer``` is being used to a ```xml_data``` topic from the ```batched_group``` consumer group:
```ruby
RSpec.describe Karafka::App.routes do
describe 'batched group' do
let(:group) do
Karafka::App.routes.find do |cg|
cg.name == 'batched_group'
end
end
describe 'xml_data topic' do
let(:topic) { group.topics.find { |ts| ts.name == 'xml_data' } }
it { expect(topic.deserializer).to eq XmlDeserializer }
end
end
end
```