Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
forked fromjjh42/mock

Mocking library for Elixir language

License

NotificationsYou must be signed in to change notification settings

techgaun/mock

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build StatusCoverage Status

Mock

A mocking library for the Elixir language.

We use the Erlangmeck library to providemodule mocking functionality for Elixir. It uses macros in Elixir to expose thefunctionality in a convenient manner for integrating in Elixir tests.

See the fullreference documentation.

Installation

First, add mock to yourmix.exs dependencies:

defdepsdo[{:mock,"~> 0.3.0",only::test}]end

and run$ mix deps.get.

Example

The Mock library provides thewith_mock macro for running tests withmocks.

For a simple example, if you wanted to test some code which callsHTTPotion.get to get a webpage but without actually fetching thewebpage you could do something like this.

defmoduleMyTestdouseExUnit.Case,async:falseimportMocktest"test_name"dowith_mockHTTPotion,[get:fn(_url)->"<html></html>"end]doHTTPotion.get("http://example.com")# Tests that make the expected callassert_calledHTTPotion.get("http://example.com")endendend

You can also assert for number of counts for a call to happen

assertcalled1,HTTPotion.get("http://example.com")assert_called1,HTTPotion.get("http://example.com")

And you can mock up multiple modules withwith_mocks.

opts List of optional arguments passed to meck.:passthrough willpassthrough arguments to the original module. Pass[] asopts if you don'tneed this.

defmoduleMyTestdouseExUnit.Case,async:falseimportMocktest"multiple mocks"dowith_mocks([{Map,[],[get:fn(%{},"http://example.com")->"<html></html>"end]},{String,[],[reverse:fn(x)->2*xend,length:fn(_x)->:okend]}])doassertMap.get(%{},"http://example.com")=="<html></html>"assertString.reverse(3)==6assertString.length(3)==:okendendend

You can mock functions that return different values depending on the input:

defmoduleMyTestdouseExUnit.Case,async:falseimportMocktest"mock functions with multiple returns"dowith_mocks(HTTPotion,[get:fn"http://example.com"->"<html>Hello from example.com</html>""http://example.org"->"<html>example.org says hi</html>"end])doassertHTTPotion.get("http://example.com")=="<html>Hello from example.com</html>"assertHTTPotion.get("http://example.org")=="<html>example.org says hi</html>"endendend

You can mock functions in the same module with different arity.The same way you could mock function with optional args.

defmoduleMyTestdouseExUnit.Case,async:falseimportMocktest"mock functions with different arity"dowith_mockString,[slice:fn(string,range)->stringend,slice:fn(string,range,len)->stringend]doassertString.slice("test",1..3)=="test"assertString.slice("test",1,3)=="test"endendend

An additional convenience macrotest_with_mock is supplied whichinternally delegates towith_mock. Allowing the above test to bewritten as follows:

defmoduleMyTestdouseExUnit.Case,async:falseimportMocktest_with_mock"test_name",HTTPotion,[get:fn(_url)->"<html></html>"end]doHTTPotion.get("http://example.com")assert_calledHTTPotion.get("http://example.com")endend

Thetest_with_mock macro can also be passed a context argumentallowing the sharing of information between callbacks and the test

defmoduleMyTestdouseExUnit.Case,async:falseimportMocksetupdodoc="<html></html>"{:ok,doc:doc}endtest_with_mock"test_with_mock with context",%{doc:doc},HTTPotion,[],[get:fn(_url,_headers)->docend]doHTTPotion.get("http://example.com",[foo::bar])assert_calledHTTPotion.get("http://example.com",:_)endend

Thewith_mock creates a mock module. The keyword list provides a setof mock implementation for functions we want to provide in the mock (inthis case justget). Insidewith_mock we exercise the test codeand we can check that the call was made as we expected usingcalled andproviding the example of the call we expected (the second argument:_ has aspecial meaning of matching anything).

You can also pass the option:passthrough to retain the original modulefunctionality. For example

defmoduleMyTestdouseExUnit.Case,async:falseimportMocktest_with_mock"test_name",IO,[:passthrough],[]doIO.puts"hello"assert_calledIO.puts"hello"endend

Thesetup_with_mocks mocks up multiple modules prior to every single testalong with calling the provided setup block. It is simply an integration of thewith_mocks macro available in this module along with thesetupmacro defined in elixir'sExUnit.

defmoduleMyTestdouseExUnit.Case,async:falseimportMocksetup_with_mocks([{Map,[],[get:fn(%{},"http://example.com")->"<html></html>"end]}])dofoo="bar"{:ok,foo:foo}endtest"setup_with_mocks"doassertMap.get(%{},"http://example.com")=="<html></html>"endend

The behaviour of a mocked module within the setup call can be overridden using anyof the methods above in the scope of a specific test. Providing this functionalitybysetup_all is more difficult, and as such,setup_all_with_mocks is not currentlysupported.

Currently, mocking modules cannot be done asynchronously, so make sure that youare not usingasync: true in any module where you are testing.

Also, because of the way mock overrides the module, it must be defined in aseparate file from the test file.

Tips

The use of mocking can be somewhat controversial. I personally think that itworks well for certain types of tests. Certainly, you should not overuse it. Itis best to write as much as possible of your code as pure functions which don'trequire mocking to test. However, when interacting with the real world (or webservices, users etc.) sometimes side-effects are necessary. In these cases,mocking is one useful approach for testing this functionality.

Also, note that Mock has a global effect so if you are using Mocks in multipletests setasync: false so that only one test runs at a time.

Help

Open an issue.

Suggestions

I'd welcome suggestions for improvements or bugfixes. Just open an issue.

About

Mocking library for Elixir language

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Languages

  • Elixir100.0%

[8]ページ先頭

©2009-2025 Movatter.jp