Giter Site home page Giter Site logo

appunite / mockery Goto Github PK

View Code? Open in Web Editor NEW
91.0 3.0 10.0 230 KB

Simple mocking library for asynchronous testing in Elixir.

Home Page: https://hex.pm/packages/mockery

License: Apache License 2.0

Elixir 100.00%
elixir-lang elixir exunit asynchronous-tests mock-library mocking

mockery's People

Contributors

amatalai avatar cjpwrs avatar esse avatar michaldolata avatar mindreframer avatar mkaszubowski avatar sionide21 avatar telnicky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mockery's Issues

Would you like this helper module?

I've written a helper module that I can work into a pull request, if you like. Here's the moduledoc and the doc for the main function:

  @moduledoc """
  A shorthand notation for `Mockery` that makes more pretty the common case
  of returning a specific return value for a given set of arguments, as
  in:

      use Given
      given Map.get(%{}, :key), return: "5"

  Note that the first argument to `given` looks like an ordinary function call.

  It is also common to have a "don't care" argument, like this:

      given Map.get(@any, :key), return: "5"

  See `given/2` for more.
  """

  @doc """
  Takes what looks like a function call, plus a return value, and arranges that
  such a function call will return the given value whenever it's made at a
  ["seam"](https://www.informit.com/articles/article.aspx?p=359417&seqNum=2)
  marked with `Mockery.mockable/1`. 

      # Code:
      ... mockable(Schema).changeset(struct, params) ...

      # Test: 
      given Schema.changeset(%Schema{}, %{age: "3"}), return: %Changeset{...}

  The function's arguments and return value can be constants, as shown
  above, or they can be calculations or variables. That can be helpful
  when the `given` appears in a test helper:

      def helper(params, cast_value, something_else) do 
        ...
        given Schema.changeset(%Schema{}, params), return: cast_value
        ...
        assert ...
      end

  A function argument can be the special value `@any` (defined when
  the module is `used`). That's useful when the argument is irrelevant
  and you don't want to have to type it out:

        given Schema.changeset(@any, params), return: cast_value

  `@any` expands to a function whose value is always `true`. More generally,
  any function used as an argument is not matched with equality. Instead, the
  call-time value is passed to the function, which should return a truthy value
  to indicate a match. So you can do this:

        given Module.f(5, &even/1), return: 8

  Notes:
  * You can provide return values for many arglist values. 
    
        given Module.f(5, &even/1), return: 8
        given Module.f(6, @any),    return: 9

  * If there's more than one match, the first is used.

  * If the same arglist is given twice, the second replaces the first.
    This is useful for `setup` methods:

        def setup do  
          given RunningExample.params(:a_runnable), return: %{}
          ...

        test "..."
          given RunningExample.params(:a_runnable), return: %{"a" => "1"}
          assert Steps.runnable(:a_runnable) == %{a: 1}
        end

  * If a function has a `given` value for one or more arglists, but none
    matched, an error is thrown.
  """
  
  defmacro given(funcall, return: value) do

Elixir compile emits warning when providing variable to assert_called list of arguments

Example code:

defmodule SomeModule do
  def execute(a), do: a
end

defmodule SomethingOther do
  import Mockery.Macro

  def new(params), do: mockable(SomeModule).execute(params)
end

Example test:

defmodule TestAppTest do
  use ExUnit.Case
  use Mockery

  describe "some context" do
    setup do
      {:ok, params: %{a: 1}}
    end

    test "it should not give a warning here", %{params: params} do
      mock(SomeModule, [execute: 1], %{"some_key" => "some value"})

      SomethingOther.new(params)

      assert_called(SomeModule, :execute, [params])
    end
  end
end

Expected result:

  • test compile and run without warnings or errors

Actual result:

  • compiler emits warning:
warning: variable "params" is unused (if the variable is not meant to be used, prefix it with an underscore)
  test/test_app_test.exs:15: TestAppTest."test some context it should not give warning here"/1

(note that line 15 is: assert_called(SomeModule, :execute, [params]))

Improve failure output when using pinned variables

As the title suggests, the output is currently not very helpful when using pinned variables.

See an example below:

assert_called Redix, :pipeline, [
  :redix,
  [
    ["HSET", ^access_token_namespace, ^id, ^access_token],
    ["EXPIRE", ^access_token_namespace, ^id, _],
    ["HSET", ^refresh_token_namespace, ^id, ^refresh_token],
    ["EXPIRE", ^refresh_token_namespace, ^id, _]
  ]
]

If then the test fails the output looks like this (output shortened by using <placeholders>):

Redix.pipeline was not called with given arguments

Given:
[:redix, [["HSET", ^access_token_namespace, ^id, ^access_token], ["EXPIRE", ^access_token_namespace, ^id, _], ["HSET", ^refresh_token_namespace, ^id, ^refresh_token], ["EXPIRE", ^refresh_token_namespace, ^id, _]]]

History:
[:redix, [["HSET", "<namespace>", "<id>", "<access token>"], ["EXPIRE", "<namespace>", "<id>", <expire>], ["HSET", "<namespace>", "<id>", "<refresh token>"], ["EXPIRE", "<namespace>", "<id>", <expire>]]]

code: assert_called Redix, :pipeline, [
stacktrace:
  ...

This makes it very, very hard to find out why a particular test fails.

Compare this to how ex_unit handles pinned variables:

match (=) failed
The following variables were pinned:
  access_token = "<access token>"
  access_token_namespace = "<namespace>"
  refresh_token = "<refresh token>"
  refresh_token_namespace = "<namespace>"
  id = <id>
code:  assert [:redix, [["HSET", ^access_token_namespace, ^id, ^access_token], ["EXPIRE", ^access_token_namespace, ^id, _], ["HSET", ^refresh_token_namespace, ^id, ^refresh_token], ["EXPIRE", ^refresh_token_namespace, ^id, _]]] = commands
right: [
         ["HSET", "<namespace>",
          "<id>",
          "<access token>"],
         ["EXPIRE", "<namespace>",
          "<id>", <expiry>],
         ["HSET", "<namespace>",
          "<id>",
          "<refresh_token>"],
         ["EXPIRE", "<namespace>",
          "<id>", <expiry>]
       ]
stacktrace:
  ...

Allow to use module attributes in assert_called

When I try to use module attributes in an assert_called match, I receive the following error:

== Compilation error in file test/authentication/storage/redis_test.exs ==
** (FunctionClauseError) no function clause matching in Kernel.@/1    
    (elixir) expanding macro: Kernel.@/1

Example for match:

assert_called Redix, :command, [:redix, ["HSET", @namespace, "key", "value"]]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.