For some time now, he has been trying to find the best solution for GenServer testing. The problem is that assert_receive has to specify the time when the message will arrive, sometimes it arrives on time and sometimes it crashes that the mailbox is empty. Do you have any cool solution for testing GenServers?
I have rewritten the code so that it is understandable to you
defmodule App.Consumer do
use Broadway
alias Broadway.Message
def start_link(_args) do
options = [
name: __MODULE__,
producer: [
module: {
BroadwayRabbitMQ.Producer,
connection: Application.get_env(:app, :uri_rabbitmq),
queue: "queue",
on_failure: :reject,
qos: [prefetch_count: 10],
declare: [durable: true],
bindings: [
{"app", routing_key: "queue.read"}
],
metadata: [:routing_key]
},
concurrency: 1
],
processors: [
default: [
concurrency: System.schedulers_online()
]
]
]
Broadway.start_link(__MODULE__, options)
end
def handle_message(_processor, message, _context) do
messenger_pid = get_messenger_pid(message)
Messenger.send_hook(messenger_pid, :message)
end
end
defmodule App.Messenger do
@moduledoc false
def send_hook(messenger_pid, value, meta \\ %{})
def send_hook(messenger_pid, value, meta) do
if not is_nil(messenger_pid) do
send(messenger_pid, {value, meta})
end
end
end
defmodule App.ConsumerTest do
use App.DataCase
alias App.Consumer
import Mock
setup_with_mocks([
{Broadway.Message, [], [failed: fn _, _ -> nil end]}
]) do
:ok
end
describe "Test Consumer" do
@good_message ~s({
"data":{
"uuid":"ec031400-1784-4e22-b117-cb62fc9e0398"
"created_at":"2022-01-03T11:16:05",
}
})
test "Test" do
ConsumerMarket.handle_message(
nil,
%{
data: @good_message,
messenger_pid: self(),
metadata: %{
routing_key: "queue.read"
}
},
nil
)
assert_receive {:message, _meta}, 100
end
end
end
With such a test, it probably won't be a problem. But if Consumer Broadway start GenServer Feed and Feed start Dynamic Supervisor GenServer JobTask and you have a lot of tests written then you will end up getting this error
test Test Consumer Market Read xxxx (App.ConsumerTest)
Assertion failed, no matching message after 100ms
Showing 1 of 1 message in the mailbox
code: assert_receive {:zzz, _meta}
mailbox:
pattern: {:zzz, _meta}
value: {:xxx, %{}}(test)