2015-06-15 11 views
6

Ho un'app Phoenix (che è solo un'ape riposante senza front-end) e uno dei controller fa alcune cose che voglio testare, ma alla fine del controller chiama un dispatcher che invia un payload a un lavoratore (eseguito sotto il poolboy) per elaborare il carico utile ricevuto in background.Come interrompere (o impedire l'esecuzione) di una chiamata a un operatore nel mio test ExUnit?

Nella mia prova di controllo, io in realtà non voglio testare la roba il lavoratore sta facendo, voglio solo sapere che il dispatcher per il lavoratore è stato chiamato con il carico utile corretto (ad es calledWith())

E idealmente la funzione del dispatcher da eliminare, quindi la cosa reale non viene mai eseguita.

Potrei passare un ulteriore parametro al dispatcher per assicurarmi che non esegua mai il codice sul lavoratore, ma ciò sembra molto disordinato, mentre uno stub sembra un'idea.

Grazie

Modifica

codice Dispatcher:

defmodule Convert.Dispatcher do 
    def dispatch(data) fo 
    spawn (fn() -> parallel(data) end) 
    end 

    def parallel(data) do 
    #pass off to poolboy 
    end 
end 

test di simulazione:

with_mock Convert.Dispatcher, [dispatch: fn(_opts) -> :ok end] do 
    response = conn(:post, "/", data) |> send_request 
    body = response.resp_body |> Poison.decode! 
    assert response.status == 201 
    assert called Convert.Dispatcher.dispatch("") 
end 
+1

Fare attenzione ad andare in giro per una libreria di derisione prima di considerare altre opzioni. Impedisce l'esecuzione simultanea del test case (a causa della modifica globale del modulo), accoppia strettamente la tua implementazione, il che significa più lavoro quando devi scambiarlo con un altro modulo e introduce nuove dipendenze. Considera invece di iniettare le tue dipendenze, come in http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/ e https://medium.com/@lasseebert/mocks-in-elixir- 7204f8cc9d0f – Dennis

risposta

7

C'è una biblioteca beffardo chiamato "mock" che è possibile utilizzare temporaneamente finta moduli in te test. Ad esempio:

defmodule MyControllerTest do 
    use ExUnit.Case, async: false 
    use RouterHelper 
    import Mock 

    setup do 
    Logger.disable(self()) 
    :ok 
    end 

    test "dispatches a worker" do 
    with_mock MyDispatcher, [dispatch: fn(_opts) -> :ok end] do 
     call(Router, :get, "/my/route") 
     assert called MyDispatcher.dispatch(foo: "bar") 
    end 
    end 
end 
+0

Grazie, sembra grandioso, ci provo io – TheStoneFox

+0

Il problema che sto ottenendo è che il mock funziona correttamente (cioè il codice non viene eseguito) ma quando provo a fare l'asserzione ottengo l'errore "La verità attesa , ho ottenuto false "- ma so che il codice viene eseguito come l'ho visto prima di aggiungere il mock:/ – TheStoneFox

+0

Sei sicuro che venga chiamato con gli argomenti previsti? –

Problemi correlati