Leave module loaded state as it was
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7b8ae59..e2e5d34 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@
 
 ## [Unreleased]
 
+### Added
+
+- Leave module loaded state as it was [\#228](https://github.com/eproxus/meck/pull/228)
+
 ## [0.9.2] - 2021-03-06
 
 ### Fixed
diff --git a/src/meck_proc.erl b/src/meck_proc.erl
index 2640236..b1500c6 100644
--- a/src/meck_proc.erl
+++ b/src/meck_proc.erl
@@ -61,7 +61,8 @@
                 passthrough = false :: boolean(),
                 reload :: {Compiler::pid(), {From::pid(), Tag::any()}} |
                           undefined,
-                trackers = [] :: [tracker()]}).
+                trackers = [] :: [tracker()],
+                restore = false :: boolean()}).
 
 -record(tracker, {opt_func :: '_' | atom(),
                   args_matcher :: meck_args_matcher:args_matcher(),
@@ -211,6 +212,7 @@
 %% @hidden
 init([Mod, Options]) ->
     validate_options(Options),
+    Restore = code:is_loaded(Mod) =/= false,
     Exports = normal_exports(Mod),
     WasSticky = case proplists:get_bool(unstick, Options) of
         true -> {module, Mod} = code:ensure_loaded(Mod),
@@ -237,7 +239,8 @@
                     was_sticky = WasSticky,
                     merge_expects = MergeExpects,
                     passthrough = Passthrough,
-                    history = History}}
+                    history = History,
+                    restore = Restore}}
     catch
         exit:{error_loading_module, Mod, sticky_directory} ->
             {stop, {module_is_sticky, Mod}}
@@ -344,11 +347,20 @@
 
 %% @hidden
 terminate(_Reason, #state{mod = Mod, original = OriginalState,
-                          was_sticky = WasSticky}) ->
+                          was_sticky = WasSticky, restore = Restore}) ->
     BackupCover = export_original_cover(Mod, OriginalState),
     cleanup(Mod),
     restore_original(Mod, OriginalState, WasSticky, BackupCover),
-    ok.
+    case Restore andalso false =:= code:is_loaded(Mod) of
+        true ->
+            % We make a best effort to reload the module here. Since this runs
+            % in a terminating process there is nothing we can do to recover if
+            % the loading fails.
+            _ = code:load_file(Mod),
+            ok;
+        _ ->
+            ok
+    end.
 
 %% @hidden
 code_change(_OldVsn, S, _Extra) -> {ok, S}.
diff --git a/test/meck_tests.erl b/test/meck_tests.erl
index 616730c..946ba7b 100644
--- a/test/meck_tests.erl
+++ b/test/meck_tests.erl
@@ -928,6 +928,20 @@
     ?assertEqual(lists:sort(Mods), lists:sort(meck:unload())),
     [?assertEqual(false, code:is_loaded(M)) || M <- Mods].
 
+reload_module_test() ->
+    false = code:purge(meck_test_module),
+    ?assertEqual({module, meck_test_module}, code:load_file(meck_test_module)),
+    ok = meck:new(meck_test_module),
+    ?assertEqual(ok, meck:unload(meck_test_module)),
+    ?assertMatch({file, _}, code:is_loaded(meck_test_module)),
+    false = code:purge(meck_test_module),
+    true = code:delete(meck_test_module),
+    ?assertEqual(false, code:is_loaded(meck_test_module)),
+    ok = meck:new(meck_test_module),
+    ?assertMatch({file, _}, code:is_loaded(meck_test_module)),
+    ?assertEqual(ok, meck:unload(meck_test_module)),
+    ?assertEqual(false, code:is_loaded(meck_test_module)).
+
 original_no_file_test() ->
     {ok, Mod, Beam} = compile:forms([{attribute, 1, module, meck_not_on_disk}]),
     {module, Mod} = code:load_binary(Mod, "", Beam),