goofansu
goofansu

Reputation: 2277

Eunit test won't wait for receive

Eunit won't wait for the receive, is there something special to eunit.

-module (test_account).

-include_lib ("eunit/include/eunit.hrl").

-compile (export_all).

login_test() ->
    {ok, Socket} = gen_tcp:connect("localhost", 5678,
        [binary, {packet, 4}]),

    RoleName = <<"abc">>,
    LenRoleName = byte_size(RoleName),

    Password = <<"def">>,
    LenPassword = byte_size(Password),

    LoginBin = <<11001:16, LenRoleName:16, RoleName/binary,
        LenPassword:16, Password/binary>>,
    gen_tcp:send(Socket, LoginBin),
    print(Socket).


print(Socket) ->
    receive
        {tcp, Socket, Data} ->
            io:format("Data=~p~n", [Data])
    end.

If I call test_account:login_test(). directly, it can receive the response.

Thank you.

Upvotes: 0

Views: 275

Answers (1)

demeshchuk
demeshchuk

Reputation: 742

My guess is there's something wrong on the listening side, like missing {packet, 4} parameter or something. I started a listening socket on the required port manually, and the test did work.

EUnit isn't really supposed to run integration tests out-of-the-box (though there are some libraries that make it somewhat convenient for integration tests as well). What you are realy supposed to do here is something like that:

main_test_() ->
    {setup,
        fun setup/0,
        fun teardown/1,
        [{"login", fun login_test/0}]
    }.

setup() ->
    process_flag(trap_exit, true),
    {ok, Pid} = my_tcp_server:start_link(),
    Pid.

teardown(Pid) ->
    exit(Pid, shutdown).

So, basically, you shouldn't rely on a separately running server when using just EUnit. Instead, you should either start it explicitly from your code or, if it's external, mock it (or just some of its parts, if the entire server code is complicated).

P.S. Don't forget the underscore at the end of 'main_test_', it's a contract for {setup, ...} and {foreach, ...} tests.

Upvotes: 2

Related Questions