PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/Machine.Specifications.Tests/Machine.Testing/TestsFor.cs

https://github.com/machine/machine.specifications
C# | 269 lines | 229 code | 40 blank | 0 comment | 9 complexity | 9cd66e922803288f52dae27b7c423f2d MD5 | raw file
Possible License(s): MIT, CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using System.Reflection.Emit;
  5. using Machine.Testing.AutoMocking;
  6. using NUnit.Framework;
  7. using Rhino.Mocks;
  8. using Rhino.Mocks.Interfaces;
  9. namespace Machine.Testing
  10. {
  11. public abstract class TestsFor<TType> where TType : class
  12. {
  13. AutoMockingContainer _container;
  14. TType _target;
  15. MockRepository _mocks;
  16. Dictionary<Type, object> _overrides;
  17. Dictionary<Type, IEventRaiser> _raisers;
  18. [ThreadStatic]
  19. static Dictionary<int, EventFireExpectation> _eventsToVerify =
  20. new Dictionary<int, EventFireExpectation>();
  21. [ThreadStatic]
  22. static int _currentEventId = 0;
  23. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  24. public enum With
  25. {
  26. Stub,
  27. StrictMock
  28. }
  29. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  30. public AutoMockingContainer Container
  31. {
  32. get { return _container; }
  33. }
  34. public TType Target
  35. {
  36. get
  37. {
  38. CreateTargetIfNeedBe();
  39. return _target;
  40. }
  41. }
  42. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  43. public MockRepository Mocks
  44. {
  45. get { return _mocks; }
  46. }
  47. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  48. public IDisposable Record
  49. {
  50. get { return Mocks.Record(); }
  51. }
  52. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  53. public IDisposable Playback
  54. {
  55. get
  56. {
  57. CreateTargetIfNeedBe();
  58. return new PlaybackAndVerifyEvents(this, Mocks.Playback());
  59. }
  60. }
  61. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  62. public IDisposable PlaybackOnly
  63. {
  64. get
  65. {
  66. using (Record)
  67. {
  68. }
  69. return Playback;
  70. }
  71. }
  72. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  73. class EventFireExpectation
  74. {
  75. bool _wasFired;
  76. string _delegateName;
  77. public bool WasFired
  78. {
  79. get { return _wasFired; }
  80. set { _wasFired = value; }
  81. }
  82. public string DelegateName
  83. {
  84. get { return _delegateName; }
  85. }
  86. public EventFireExpectation(string delegateName)
  87. {
  88. _wasFired = false;
  89. _delegateName = delegateName;
  90. }
  91. }
  92. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  93. class PlaybackAndVerifyEvents : IDisposable
  94. {
  95. readonly TestsFor<TType> _tests;
  96. readonly IDisposable _playback;
  97. public PlaybackAndVerifyEvents(TestsFor<TType> tests, IDisposable playback)
  98. {
  99. _tests = tests;
  100. _playback = playback;
  101. }
  102. public void Dispose()
  103. {
  104. _playback.Dispose();
  105. _tests.VerifyEvents();
  106. }
  107. }
  108. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  109. public void VerifyEvents()
  110. {
  111. foreach (var pair in _eventsToVerify)
  112. {
  113. Assert.IsTrue(pair.Value.WasFired, String.Format("{0} was not fired.", pair.Value.DelegateName));
  114. }
  115. }
  116. [SetUp]
  117. public void BaseSetup()
  118. {
  119. _overrides = new Dictionary<Type, object>();
  120. _raisers = new Dictionary<Type, IEventRaiser>();
  121. _mocks = new MockRepository();
  122. _container = new AutoMockingContainer(_mocks);
  123. _eventsToVerify.Clear();
  124. _currentEventId = 0;
  125. SetupContainer();
  126. _container.Initialize();
  127. _container.PrepareForServices();
  128. _container.Start();
  129. _target = null;
  130. BeforeEachTest();
  131. }
  132. void CreateTargetIfNeedBe()
  133. {
  134. if (_target != null) return;
  135. _target = _container.Resolve.New<TType>(new List<object>(_overrides.Values).ToArray());
  136. }
  137. public virtual void SetupContainer()
  138. {
  139. }
  140. public virtual void BeforeEachTest()
  141. {
  142. }
  143. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  144. public void Override<T>(With what)
  145. {
  146. switch (what)
  147. {
  148. case With.Stub:
  149. Override(Mocks.Stub<T>());
  150. break;
  151. case With.StrictMock:
  152. Override(Mocks.StrictMock<T>());
  153. break;
  154. default:
  155. throw new Exception("Unknown With");
  156. }
  157. }
  158. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  159. public void Override<T>(T service)
  160. {
  161. _overrides.Add(typeof(T), service);
  162. }
  163. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  164. public T The<T>()
  165. {
  166. if (_overrides.ContainsKey(typeof(T)))
  167. {
  168. return (T)_overrides[typeof(T)];
  169. }
  170. return _container.Get<T>();
  171. }
  172. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  173. public void FireEventOn<T>(params object[] args)
  174. {
  175. if (!_raisers.ContainsKey(typeof(T)))
  176. {
  177. throw new Exception(
  178. String.Format("You must first call PrimeEventFiringOn<{0}>(x => x.Event += null) in the Record phase",
  179. typeof(T).Name));
  180. }
  181. List<object> list = new List<object>(args);
  182. list.Insert(0, The<T>());
  183. _raisers[typeof(T)].Raise(list.ToArray());
  184. }
  185. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  186. public void PrimeEventFiringOn<T>(Action<T> eventPlusEqualNull)
  187. {
  188. if (_raisers.ContainsKey(typeof(T)))
  189. {
  190. throw new Exception(
  191. String.Format(
  192. "You can only prime one event at a time for {0}. If you must prime multiple, try using LastCall.GetEventRaiser the normal way.",
  193. typeof(T).Name));
  194. }
  195. eventPlusEqualNull(The<T>());
  196. _raisers[typeof(T)] = LastCall.GetEventRaiser();
  197. }
  198. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  199. static void RegisterEventFiring(int eventId)
  200. {
  201. _eventsToVerify[eventId].WasFired = true;
  202. }
  203. [ObsoleteEx(Message = "Use FluentAssertions or Mocking library of choice directly", RemoveInVersion = "0.9", TreatAsErrorFromVersion = "0.8")]
  204. public T NewEventFireExpectation<T>() where T : class
  205. {
  206. _eventsToVerify[_currentEventId] = new EventFireExpectation(typeof(T).Name);
  207. MethodInfo registerMethod = typeof(TestsFor<TType>).GetMethod("RegisterEventFiring",
  208. BindingFlags.Static | BindingFlags.NonPublic);
  209. MethodInfo invokeMethod = typeof(T).GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance);
  210. ParameterInfo[] parameters = invokeMethod.GetParameters();
  211. Type[] parameterTypes = new Type[parameters.Length];
  212. for (int i = 0; i < parameters.Length; ++i)
  213. {
  214. parameterTypes[i] = parameters[i].ParameterType;
  215. }
  216. if (invokeMethod == null)
  217. {
  218. throw new Exception(String.Format("Cannot find Invoke method on {0}, is it a Delegate?", typeof(T).Name));
  219. }
  220. DynamicMethod method = new DynamicMethod("__FireEvent" + _currentEventId, invokeMethod.ReturnType, parameterTypes,
  221. this.GetType(), true);
  222. ILGenerator ilGenerator = method.GetILGenerator();
  223. ilGenerator.Emit(OpCodes.Ldc_I4, _currentEventId++);
  224. ilGenerator.Emit(OpCodes.Call, registerMethod);
  225. ilGenerator.Emit(OpCodes.Ret);
  226. return method.CreateDelegate(typeof(T)) as T;
  227. }
  228. }
  229. }