Godfrey

Godfrey

How to approach OBAN Pro testing workflow with 3 workers?

Good Day ,

I have a specific workflow with ,for example (Workers A,B and C) . So when worker A executes successfully, it records results which have to be used by worker B and C.
So now I want to do Unit testing on Worker B and C , how would you advise in going about that ? Because now when I run maybe a perform_job on my unit test , where will it get those recorded result since an Oban Unit test shouldn’t be hitting the DB , How do I make it pass ???

Most Liked

sorentwo

sorentwo

Oban Core Team

If a job is relying on the output of another, then an integration test may be appropriate. You can test all of the jobs together with run_workflow/2:

assert %{completed: 3} =
         Workflow.new()
         |> Workflow.add(:a, MyFlow.new(%{}))
         |> Workflow.add(:b, MyFlow.new(%{}), deps: [:a])
         |> Workflow.add(:c, MyFlow.new(%{}), deps: [:b])
         |> run_workflow()

If the logic in those jobs is complex or the test requires too much setup, you can inject data through the args. The trick is using args_schema with the :term type, so you can stub any value:

defmodule MyApp.MyFlow do
  use Oban.Pro.Workers.Workflow

  args_schema do
    field :id, :id
    field :result, :term
  end

  @impl true
  def process(job) do
    {:ok, result} = fetch_lazy(job)
    ...
  end

  defp fetch_lazy(%{args: %{result: nil}} = job) do
    job
    |> Workflow.all_jobs(only_deps: true)
    |> List.first()
    |> fetch_recorded()
  end

  defp fetch_lazy(%{args: %{result: result}}), do: {:ok, result}
end

Then use perform_job/3 as you normally would in your test:

assert {:ok, _} = perform_job(MyFlow, %{id: 123, result: {:some, :thing}})
mtunski

mtunski

I always thought of that this way: these unit-test Oban helpers just call Worker.process/perform, without inserting the job to the database to execute it, as Oban would “normally” do.

But regardless of this behaviour, if the worker code (implementation in process/perform) itself has to reach the database - and it has if it tries reading the results of a job it depends on - it’s something different and 100% legit.

sorentwo

sorentwo

Oban Core Team

The discrepancy seems to be around the term “unit”. Pure tests that don’t touch the db are a fine ideal, but the sandbox makes db interaction so quick and isolated that it’s not always worth it.

I’d argue that a workflow test, especially one that relies on fetching results of another job, should be tested with the database involved.

Where Next?

Popular in Questions Top

_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39297 209
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

We're in Beta

About us Mission Statement