https://github.com/renderedtext/fun-registry
https://github.com/renderedtext/fun-registry
Last synced: 4 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/renderedtext/fun-registry
- Owner: renderedtext
- License: apache-2.0
- Created: 2018-03-30T16:56:10.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2025-02-20T15:24:44.000Z (over 1 year ago)
- Last Synced: 2025-08-18T20:47:04.445Z (10 months ago)
- Language: Elixir
- Size: 14.6 KB
- Stars: 2
- Watchers: 4
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# FunRegistry - Function Registry
A dynamic function registry, useful for implementing processes that can be
modified during their lifetime.
An example use case is the creation of fake GRPC that emulates remote servers.
This is useful in development and test environments.
## Installation
Add the following to your mixfile:
```elixir
def deps do
[
{:fun_registry, github: "renderedtext/fun-registry", only: [:dev, :test]}
]
end
```
## Example usage for creating fake GRPC servers
First, we will create a fake server that emulates a remote Calculator service:
``` elixir
defmodule CalculatorService do
use GRPC.Server, service: Calculator.Service
def add(req, stream) do
# instead of an implementation, we will relly on the FunRegistry
# to fetch and run a function
FunRegistry.run(__MODULE__, :add, [req, stream])
end
end
GRPC.Server.start(CalculatorService, 50051)
```
Let's connect to the calculator service and invoke some rpc methods:
``` elixir
def calculate_remotly(a, b) do
#
# in dev and test this is set to "localhost:50051"
# in prod we will connect to a real server
#
endpoint = Application.get_env(:my_app, :calculator_endpoint)
{:ok, channel} = GRPC.Server.connect(endpoint)
req = Calculator.AddRequest.new(a: 12, b: 13)
{:ok, res} = Calculator.Stub.add(req)
res.result
end
```
Now, we can use the function registry to simulate the behaviour of the remote
server:
``` elixir
setup do
FunRegistry.clear!
end
test "calculate-remotly is able to communicate with remote servers" do
# first, we will stub the behaviour of the server
FunRegistry.set!(CalculatorService, :add, fn(req, _) ->
Calculator.AddResponse.new(result: req.a + req.b)
end)
assert calculate_remotly(1, 2) == 10
end
test "calculate-remotly is able to communicate with remote servers stubbed version" do
# instead of functions, we can set a stubbed response directly
FunRegistry.set!(CalculatorService, :add, Calculator.AddResponse.new(result: 10))
assert calculate_remotly(1, 2) == 10
end
test "calculate-remotly passes the correct data to the remote service" do
# we will store the values in an agent
{:ok, agent} = Agent.new(fn -> nil end)
# instead of functions, we can set a stubbed response directly
FunRegistry.set!(CalculatorService, :add, fun(req, _) ->
Agent.update(agent, fn state -> {req.a, req.b} end)
end)
# execute the remote call
calculate_remotly(1, 2) == 10
# fetch the data that was received by the remote server
values = Agent.get(agent, pid, fn s -> s end)
# make sure that the remote server got the correct info
assert values == {1, 2}
end
test "calculate service is too slow" do
# first, we will stub the behaviour of the server
FunRegistry.set!(CalculatorService, :add, fun(_, _) ->
:timer.sleep(5000)
end)
assert_raise fn -> calculate_remotly(1, 2) end)
end
test "calculate service is broken" do
# first, we will stub the behaviour of the server
FunRegistry.set!(CalculatorService, :add, fun(_, _) ->
raise "I don't feel well"
end)
assert_raise fn -> calculate_remotly(1, 2) end)
end
```
## License
This software is licensed under [the Apache 2.0 license](LICENSE).