# TestReflector
## Installation
Soon (but not yet) it will be [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `test_reflector` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:test_reflector, "~> 0.1.1"}
]
end
```
## Pattern Name
TestReflector
## Problem
In a TestCase how do we:
1. assert that dependent module-functions were called by the Code-Under-Test?
1. assert that the correct arguments were passed to the dependent module-functions?
1. stub out return data that the dependent module-function should return?
## Context
We are writing Micro-Tests, aka Unit-Tests.
https://www.artima.com/weblogs/viewpost.jsp?thread=126923
Classic blog post by Mike Feathers and what makes unit different from Integration testing. [A Set of Unit Testing Rules](https://www.artima.com/weblogs/viewpost.jsp?thread=126923)
I suggest that in Elixir we can call this `Module testing`. And limit the test to one module at a time.
## Solution
Inject into the Code-Under-Test a **Reflector** with the same interface as the real depedency.
* A **Reflector** is a kind of *Test Double* that has the same interface as the dependency (sometimes using a @behaviour)
* The interface function is stubbed by a default return value, and can be stashed with a customreturn value per test
* The **Reflector** sends a message back to the test-process when the interface function is called.
* The message sent back to the test-process contains the name of the called function and the arguments
## Limitations
* Reflectors are limited for when the test and target code are in the same process. This is actually good because it helps us keep the tests smaller and more focused.
---
## Example using Reflector in a test
See the real usage in: `TestReflector.DemoTest`
```
@deps %{ needed: DependentReflector }
test "some test pseudo code for demo purposes" do
# Given
resource = build(:resource)
DependentReflector.stash_get({:ok, 42})
# When
result = TargetCode.a_function_that_calls_dependent_get(@params, @deps)
# Then
assert {:ok, asset} == result
assert asset.resource_id == resource.id
assert_receive {:get, _}
end
```
## Defining the ResourceReflector
provide only semantically meaningful parts
* the message reflected back depends on the arity
* **my_function()** sends back **:name_of_function**
* **my_function(arg1)** sends back **{:name_of_function, arg_1}**
* **my_function(arg1, arg2)** sends back **{:name_of_function, arg1, arg2}**
* the function return value is either
* the default defined in the macro call, or
* whatever _term_ was stashed for that scope and function name
```
defmodule ResourceReflector do
@behaviour Somewhere.ResourceBehaviour
# scope, function, default-result
reflector(:resource, :all, [])
reflector(:resource, :get, {:ok, %{}})
reflector(:resource, :update, {:ok, %{}})
reflector(:resource, :create, {:ok, %{}})
reflector(:resource, :delete, :ok)
end
```