testing 2023-05-31

Hi, I’m using testcontainers (kafka etc) for integration tests. This means that only after the test begins (at runtime) I have the address of these containers, and can populate them in the system config. I’m using juxt’s aero for configuration, and the #ref feature of aero for repeating kafka address for each producer/consumer, like so (simplified):

{:kafka-address #or [#env KAFKA_ADDRESS "prod.address:9092"]
 :producer1 {:brokers #ref [:kafka-address]}
 :consumer1 {:brokers #ref [:kafka-address]}
 ...}
Now the ugly part: For integration tests I first start the kafka container, get its address, and then have to override the config somehow for each of the kafka clients, missing the point of using #ref. Instead, I experimented with providing environment variables while reading the config at test time, by redefining aero.core/get-env and returning test values:
(let [aero-get-env @#'aero/get-env
      get-test-env (fn [s]
                     (case (str s)
                       "KAFKA_ADDRESS" (testcontainer-address)
                       (aero-get-env s)))]
  (with-redefs [aero/get-env get-test-env]
    (run-system))
It’s the only way I’ve found to minimize extra test setup logic (overriding each client config), and use aero’s features. Is there a better way to do this?