Skip to content

Instantly share code, notes, and snippets.

@blairconrad
Last active September 29, 2016 18:51
Show Gist options
  • Save blairconrad/65c069daa92309793050bbe50272f8d1 to your computer and use it in GitHub Desktop.
Save blairconrad/65c069daa92309793050bbe50272f8d1 to your computer and use it in GitHub Desktop.
SelfInitializedFakes
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace SelfInitializedFakes
{
using FakeItEasy;
public static class SelfInitializedFake
{
private static IDictionary<string, IEnumerable<SavedCall>> savedCallCatalogue =
new Dictionary<string, IEnumerable<SavedCall>>();
public static TClass Create<TClass>(TClass actual, string savedCallKey)
{
var fake = A.Fake<TClass>();
IEnumerable<SavedCall> savedCalls;
savedCallCatalogue.TryGetValue(savedCallKey, out savedCalls);
if (savedCalls == null)
{
var newSavedCalls = new List<SavedCall>();
savedCallCatalogue[savedCallKey] = newSavedCalls;
SetupRecordingFake(actual, newSavedCalls, fake);
}
else
{
LoadSavedCalls(savedCalls, fake);
}
return fake;
}
private static void LoadSavedCalls(IEnumerable<SavedCall> savedCalls, object fake)
{
foreach (var savedCall in savedCalls)
{
A.CallTo(fake).WithNonVoidReturnType()
.Where(call => call.Method == savedCall.Method)
.Returns(savedCall.ReturnValue);
}
}
private static void SetupRecordingFake<TClass>(TClass actual, IList<SavedCall> newSavedCalls, TClass fake)
{
A.CallTo(fake).Invokes(call =>
{
call.Method.Invoke(actual, call.Arguments.ToArray());
newSavedCalls.Add(new SavedCall {Method = call.Method});
});
A.CallTo(fake).WithNonVoidReturnType().ReturnsLazily(call =>
{
var result = call.Method.Invoke(actual, call.Arguments.ToArray());
newSavedCalls.Add(new SavedCall {Method = call.Method, ReturnValue = result});
return result;
});
}
}
internal class SavedCall
{
public MethodInfo Method { get; set; }
public object ReturnValue { get; set; }
}
}
namespace SelfInitializedFakes.Tests
{
using System;
using NUnit.Framework;
public class Tests
{
[Test]
public void Test1()
{
var fake = SelfInitializedFake.Create<AService>(new AService(), nameof(Test1));
Assert.That(fake.GetCount("hippo"), Is.EqualTo(7));
}
[Test]
public void Test2()
{
var fake1 = SelfInitializedFake.Create<AService>(new AService(), nameof(Test2));
Assert.That(fake1.GetCount("hippo"), Is.EqualTo(7));
var fake2 = SelfInitializedFake.Create<AService>(new AService(), nameof(Test2));
Assert.That(fake2.GetCount("hippo"), Is.EqualTo(7));
}
}
public class AService
{
private bool wasAlreadyCalled = false;
public virtual int GetCount(string id)
{
if (wasAlreadyCalled)
{
throw new InvalidOperationException("I was already called");
}
wasAlreadyCalled = true;
return 7;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment