Mocking with s3 ex_aws_s3

I want to mock the test with s3 library just to make sure my module is working. This is what i have done so far but i don’t want to use aws keys and secret what else i need to do so my testing scenario don’t use the keys and just test the module

uploads_test.ex

defmodule SignatureWeb.UploadsTest do
  use ExUnit.Case, async: false
  alias Signature.Uploads
  import Mox

  setup :verify_on_exit!

  describe "upload/1" do
    test "write s3 bucket with file and path name and return ok with s3 path" do
      content = "signature"

     SignatureWeb.ExAwsHttpMock
      |> expect(:request, 1, fn _method, _url, _body, _headers, _opts ->
        {:ok, %{status_code: 200}}
      end)

      assert Uploads.upload(content) == {:ok, "signatures/signature"}
    end
  end
end

uploads.ex ( upload module which logic i want to test in test )

defmodule SignatureWeb.Uploads do
  def upload(content) do
    # path to bucket + filename
    s3_path = "signatures/#{content}"

    bucket_name =
      :email_messaging
      |> Application.fetch_env!(__MODULE__)
      |> Keyword.fetch!(:bucket_name)

    bucket_name
    |> ExAws.S3.put_object(s3_path, content)
    |> ExAws.request()
    |> handle_aws_response(s3_path)
  end

  defp handle_aws_response({:ok, _}, s3_path), do: {:ok, s3_path}
  defp handle_aws_response({:error, reason}, _), do: {:error, reason}
end

You cannot hardcode ExAws.request() if you want your code to use your mock for testing. You need to use some means of altering the module you‘re calling the request/1 function on.

I am doing something similiar also with Mox.

First i create a Impl file:

stats_logs_impl.ex

defmodule Stats.Logs.Impl do
  @callback fetch(Date.t(), String.t()) :: String.t()
end

then i create the API file:

stats_logs_impl.ex

defmodule Stats.Logs do
  @behaviour Stats.Logs.Impl

  @impl true
  def fetch(date, bucket), do: impl().fetch(date, bucket)

  defp impl, do: Application.get_env(:stats_logs, :impl, Stats.Logs.S3)
end

And finally the implementation

stats_logs_s3.ex

defmodule Stats.Logs.S3 do
  @behaviour Stats.Logs.Impl

  @impl true
  def fetch(%Date{} = date, bucket) do
    ...
  end
end

With this setup i can easily mock the module Stats.Log and its function fetch/2.