2017-08-03 22 views

回答

4

Elixir有many mocking libraries,大部分都是基於erlang的meck庫。 Jose Valim的 This blog post涵蓋了替代模擬框架,以支持簡單的存根,協議或回調函數。

Mock

這是一個很好的選擇,如果你想在全球範圍內存根出了可以從代碼中你無法控制(第三方軟件包或標準庫)調用的函數。缺點是當你使用這種方法時你的測試不能異步運行。

use ExUnit.Case, async: false 
import Mock 

test "test_name" do 
    with_mock HTTPotion, [get: fn(_url) -> "<html></html>" end] do 
     HTTPotion.get("http://example.com") 
     # Tests that make the expected call 
     assert called HTTPotion.get("http://example.com") 
    end 
    end 

Stubr

此庫,它幫助你在,然後可以作爲參數傳遞給其他函數傳遞現有模塊創建存根稍有不同:

test "create a stub of Timex.now/0 and defer on all other functions" do 
    fixed_time = Timex.to_datetime({2999, 12, 30}) 

    timex_stub = Stubr.stub!([now: fn -> fixed_time end], module: Timex, auto_stub: true) 

    assert timex_stub.now == fixed_time 
    assert timex_stub.before?(fixed_time, timex_stub.shift(fixed_time, days: 1)) 
end 

Syringe

此庫使用inject宏來允許您換出模塊依賴關係w母雞運行測試。它要求你修改你的代碼,但作爲回報,你可以異步運行測試。

defmodule MyThing do 
    def do_mine_things do 
    1 + 2 
    end 
end 

defmodule MyModule do 
    use Injector 

    inject MyThing, as: Mine 

    def do_things do 
    Mine.do_mine_things 
    end 
end 

defmodule MyModuleTest do 
    use ExUnit.Case, async: true 
    import Mocker 

    test "Mine must be called" do 
    mock(MyThing) 
    assert MyModule.do_things == nil 
    intercept(MyThing, :do_mine_things, nil, with: fn() -> "my mocked return" end) 
    assert MyModule.do_things == "my mocked return" 
    assert was_called(MyThing, :do_mine_things, nil) == twice # success 
    end 
end 

Mockery

注射器相似,你必須修改代碼,以用於測試動態代理。當使用這個庫,你用模塊聲明依賴屬性:

defmodule MyApp.Controller do 
    @service Mockery.of(MyApp.UserService) 

    def all do 
    @service.users() 
    end 
end 

然後在測試:

# mock MyApp.UserService.users/0 
mock MyApp.UserService, [users: 0], "mock" 
assert MyApp.Controller.all() == "mock"