Using mocks in tests?

586 views
Skip to first unread message

ma...@aravindh.io

unread,
Oct 6, 2014, 6:54:08 AM10/6/14
to elixir-l...@googlegroups.com
Hi, I am an elixir newbie and have been trying out the language for a week now. I have a basic question regarding unit testing. I want the answer from the elixir community perspective as to whether we test external calls using mocking?
 
Lets say that I have the following code:

def process do
   result
=Math.sin(1)
   result
*2
end

In the above code, in C# which is an object oriented language, I will create a mock for sin method and test whether it was called. My view is ideally in a functional language which should not depend on state unless interacting with external components, it is enough to test the final result of the function. But thats not always the case as code usually interacts with outside components. If I dont create a mock for the Math module, that function will actually be called and my test execution time will increase. I want a suggestion from the community on how to proceed on this. 


Pardon me if this is a dumb question. I am new to pure functional programming. In scala, I used to write functional code with minimal state and still I was mocking external calls. I was not able to see any mocking in some of the elixir code bases i saw in github. Am I missing something?

Thanks
Aravindh.S

José Valim

unread,
Oct 6, 2014, 7:17:14 AM10/6/14
to elixir-l...@googlegroups.com
For cases like this, I would pass the Math module as argument:

    def process(math) do
      result = math.sin(1)
      result * 2
    end

And then define a module during test that provides the semantics you want during test. If it is about state, the state is likely in a process, which you can also create and pass as argument to whatever you are testing. So far I haven't needed a mock library in Elixir. :)



José Valim
Skype: jv.ptec
Founder and Lead Developer

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

ma...@aravindh.io

unread,
Oct 6, 2014, 7:33:41 AM10/6/14
to elixir-l...@googlegroups.com, jose....@plataformatec.com.br
Agreed. You are doing a dependency injection sort of thing where you are avoiding internal state and a function will act only using the parameters passed into it. It is perfectly fine for a referentially transparent function. But is this the case through out the code?   If we pass the dependency as an argument to the function, at some point in the initial stage, we will be passing the actual module.  What should be done in that case? I am new to writing code in a purely functional language. 

PS: I just had a conv with eric in irc and he pointed me towards using behaviours and stubs. 

José Valim

unread,
Oct 6, 2014, 7:48:03 AM10/6/14
to elixir-l...@googlegroups.com
It depends a lot on the use case. In some cases I would make the most common value a default argument:

    def process(math \\ Math)

In some other cases, even more when we are talking about GenServer/GenEvent/process with state, the "dependency" will be passed just once on initialization and then you keep it around for everything else.



José Valim
Skype: jv.ptec
Founder and Lead Developer

Patrick Gombert

unread,
Oct 6, 2014, 9:13:34 AM10/6/14
to elixir-l...@googlegroups.com

I wrote a very half-baked module mocking library a little while ago.

https://github.com/patrickgombert/mockerator

I was using it to mock http libraries.

Eduardo Gurgel

unread,
Oct 6, 2014, 8:16:25 PM10/6/14
to elixir-l...@googlegroups.com
You can probably just use meck[https://github.com/eproxus/meck] so you don't need to change your code to be "testable". 

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Eduardo

Carles Miralles

unread,
Jul 20, 2015, 7:35:33 AM7/20/15
to elixir-l...@googlegroups.com, jose....@plataformatec.com.br
Indeed isn't necessary pass math as injection, mocking module Math from the test is enough, you can write something like (with ESpec)
...
before do
allow(Math).to accept(sin)
process()
end
it do: expect(Math).to accepted(:sin)
...
Reply all
Reply to author
Forward
0 new messages