Search code examples
unit-testingjulia

Julia - Use mock to test database query


I would like to test that a function, doing a request on a database and returning the answer parsed. I don't want to do a real call to my database, because the data in my database will change, so I want to mock it.

I did an example here follow. How can I mock the LibPQ.Connection object? Because otherwise I have to pass a real connection object, but I don't use it as I mock the libPQ.execute? I can not use nothing as sugested in my example, because the function libPQ.execute expects an object of type libPQ.connection, it is not working with nothing.

using Test
using Pretend
using LibPQ
using DataFrames

function function_to_test(conn::LibPQ.Connection)::MyStruct
    sql = "select * from my_table;"

    result = execute(conn, sql)

    # Parse my result and insert it into my struct

    return my_struct
end


Pretend.activate()
@testset verbose = true "Test my function" begin
    @testset "Mock LibPQ.execute" begin
        conn = nothing

        @mockable LibPQ.execute(conn::LibPQ.Connection, query::String)

        fake_execute(::Nothing, ::String) = [Dict("some_string" => "string", "some_int" => 234)]
        apply(execute => fake_execute) do
            @test typeof(function_to_test(conn)) == MyStruct
        end
    end
end


Solution

  • The function you want to test must get a LibPQ.connection object as an input. You specify that by saying conn::LibPQ.Connection in the function definition.

    If that's not what you want to test, my suggestion would be to separate the database querying and the parsing.

    # getting the object to parse
    function get_data(conn::LibPQ.Connection)
        # ...
        return stuff
    end
    
    # parsing stuff
    function function_to_test(stuff)::MyStruct
        # Parse my result and insert it into my struct
    
        return my_struct
    end
    
    # in the actual code you can then do
    get_data(conn) |> function_to_test
    

    ...and in the test you can hard-code a stuff object and feed it to the function_to_test function.