# Question on mocking of arbitrary function for testing

**URL:** <https://discourse.julialang.org/t/question-on-mocking-of-arbitrary-function-for-testing/52443>\
**Category:** New to Julia\
**Tags:** question, testing\
**Created:** [December 27, 2020, 4:55am UTC](https://discourse.julialang.org/t/question-on-mocking-of-arbitrary-function-for-testing/52443 "2020-12-27T04:55:00Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![asyrov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/asyrov/32/13578_2.png) [@asyrov](https://discourse.julialang.org/u/asyrov)\
**Post date:** [December 27, 2020, 4:55am UTC](https://discourse.julialang.org/t/question-on-mocking-of-arbitrary-function-for-testing/52443/1 "2020-12-27T04:55:00Z")

</div>

As I understand, Mocking package is mostly used for this. Something like:

```julia
using Mocking
function foo()
     @mock(bar())

```

Is there a way to avoid @mock? It looks a bit artificial. My understanding is that it is easy to just redefine function in unit test to what I want, but I cannot find a way how to restore original.

(note, this is “first steps” question)

Thank you very much,

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [December 27, 2020, 7:33am UTC](https://discourse.julialang.org/t/question-on-mocking-of-arbitrary-function-for-testing/52443/2 "2020-12-27T07:33:34Z")

</div>

There is a [SimpleMock.jl](https://github.com/JuliaTesting/SimpleMock.jl) which can do what you want. Unfortunately it is rather limited in functionality and broken on Julia nightly as far as I know.

---

<div class="post-metadata">

**Author:** ![asyrov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/asyrov/32/13578_2.png) [@asyrov](https://discourse.julialang.org/u/asyrov)\
**Post date:** [December 27, 2020, 9:38pm UTC](https://discourse.julialang.org/t/question-on-mocking-of-arbitrary-function-for-testing/52443/3 "2020-12-27T21:38:23Z")

</div>

I looked over this SimpleMock.jl and found it relies on Cassette.jl, which is just what I wanted:

So this below example does replaces sin function with cos:

```julia
using Cassette: prehook, @overdub, @context

@context Sin2Cos
Cassette.overdub(::Sin2Cos, ::typeof(sin), x) = cos(x)

function myprogram()
	alpha = 0.0
	println("sin($(alpha)) is $(sin(alpha))")
	println("cos($(alpha)) is $(cos(alpha))")
end

myprogram()

println("Now, changing sin to cos:")
Cassette.overdub(Sin2Cos(), myprogram)

```

Thanks a lot for helping!

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [December 28, 2020, 6:25am UTC](https://discourse.julialang.org/t/question-on-mocking-of-arbitrary-function-for-testing/52443/4 "2020-12-28T06:25:51Z")

</div>

You could also try my Pretend.jl package.

[https://github.com/tk3369/Pretend.jl](https://github.com/tk3369/Pretend.jl)

---

<div class="post-metadata">

**Author:** ![asyrov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/asyrov/32/13578_2.png) [@asyrov](https://discourse.julialang.org/u/asyrov)\
**Post date:** [December 28, 2020, 6:48am UTC](https://discourse.julialang.org/t/question-on-mocking-of-arbitrary-function-for-testing/52443/5 "2020-12-28T06:48:17Z")

</div>

Thank you very much for reply. Yet, this approach uses idea that “any function that may need to be mocked should be prefixed with @mockable” which I wanted to avoid.

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [December 28, 2020, 7:10am UTC](https://discourse.julialang.org/t/question-on-mocking-of-arbitrary-function-for-testing/52443/6 "2020-12-28T07:10:48Z")

</div>

Fair enough 🙂

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [December 28, 2020, 9:46am UTC](https://discourse.julialang.org/t/question-on-mocking-of-arbitrary-function-for-testing/52443/7 "2020-12-28T09:46:30Z")

</div>

This is my first experiments with this sort of tooling, so it can be suboptimal, but instead of Cassette.jl one can use [IRTools.jl](https://github.com/FluxML/IRTools.jl).

Considering the same function `myprogram`

```julia
function myprogram()
	alpha = 0.0
	println("sin($(alpha)) is $(sin(alpha))")
	println("cos($(alpha)) is $(cos(alpha))")
end

```

One can either work with IR directly

```julia
using IRTools: IR, xcall, isexpr

@dynamo function sin2cos(a...)
    ir = IR(a...)
    ir === nothing && return
    for (x, stmt) in ir
        isexpr(stmt.expr, :call) || continue
        fn = stmt.expr.args[1]
        if fn isa GlobalRef && fn.name == :sin
            ir[x].expr.args[1] = GlobalRef(Base, :cos)
        else
            ir[x] = xcall(sin2cos, stmt.expr.args...)
        end
    end
    return ir
end

julia> sin2cos() do
           myprogram()
       end
sin(0.0) is 1.0
cos(0.0) is 1.0

```

or even better, use multiple dispatch

```julia
using IRTools: IR, recurse!

mock(::typeof(sin), x) = cos(x)
@dynamo function mock(a...)
    ir = IR(a...)
    ir === nothing && return
    recurse!(ir)
    return ir
end

julia> mock() do
           myprogram()
       end
sin(0.0) is 1.0
cos(0.0) is 1.0

```

and of course it can substitute any number of function calls simultaneously

```julia
mock(::typeof(sin), x) = cos(x)
mock(::typeof(cos), x) = sin(x)

julia> mock() do
           myprogram()
       end
sin(0.0) is 1.0
cos(0.0) is 0.0

```
