object IProxyFactory.GenerateProxy(ICallRouter callRouter, Type typeToProxy, Type[] additionalInterfaces, object[] constructorArguments) { // TODO: // * new type MockCtorPlaceholder in elevated assy // * generate new empty ctor that takes MockCtorPlaceholder in all mocked types // * support ctor params. throw if foudn and not ForPartsOf. then ForPartsOf determines which ctor we use. // * have a note about static ctors. because they are special, and do not support disposal, can't really mock them right. // best for user to do mock/unmock of static ctors manually (i.e. move into StaticInit/StaticDispose and call directly from test code) object proxy; var substituteConfig = ElevatedSubstitutionContext.TryGetSubstituteConfig(callRouter); if (typeToProxy.IsInterface || substituteConfig == null) { proxy = m_DefaultProxyFactory.GenerateProxy(callRouter, typeToProxy, additionalInterfaces, constructorArguments); } else if (typeToProxy == typeof(SubstituteStatic.Proxy)) { if (additionalInterfaces != null && additionalInterfaces.Any()) { throw new SubstituteException("Cannot substitute interfaces as static"); } if (constructorArguments.Length != 1) { throw new SubstituteException("Unexpected use of SubstituteStatic.For"); } // the type we want comes from SubstituteStatic.For as a single ctor arg var actualType = (Type)constructorArguments[0]; proxy = CreateStaticProxy(actualType, callRouter); } else { // requests for additional interfaces on patched types cannot be done at runtime. elevated mocking can't, // by definition, go through a runtime dynamic proxy generator that could add such things. if (additionalInterfaces.Any()) { throw new SubstituteException("Cannot add interfaces at runtime to patched types"); } if (substituteConfig == SubstituteConfig.OverrideAllCalls) { // overriding all calls includes the ctor, so it makes no sense for the user to pass in ctor args if (constructorArguments.Any()) { throw new SubstituteException("Do not pass ctor args when substituting with elevated mocks (or did you mean to use ForPartsOf?)"); } // but we use a ctor arg to select the special empty ctor that we patched in constructorArguments = k_MockedCtorParams; } proxy = Activator.CreateInstance(typeToProxy, constructorArguments); GetRouterField(typeToProxy).SetValue(proxy, callRouter); } return(proxy); }
public static IDisposable AutoHook() { var hookedContext = SubstitutionContext.Current; var thisContext = new ElevatedSubstitutionContext(hookedContext); SubstitutionContext.Current = thisContext; return(new DelegateDisposable(() => { if (SubstitutionContext.Current != thisContext) { throw new SubstituteException("Unexpected hook in place of ours"); } SubstitutionContext.Current = hookedContext; })); }
public static IDisposable AutoHook(string assemblyLocation) { var hookedContext = SubstitutionContext.Current; var thisContext = new ElevatedSubstitutionContext(hookedContext); SubstitutionContext.Current = thisContext; // TODO: return a new IDisposable class that also contains the list of patch results, then in caller verify that against expected (don't want to go too wide) var patchAllDependentAssemblies = ElevatedWeaver.PatchAllDependentAssemblies( new NPath(assemblyLocation), PatchOptions.PatchTestAssembly).ToList(); return(new DelegateDisposable(() => { if (SubstitutionContext.Current != thisContext) { throw new SubstituteException("Unexpected hook in place of ours"); } SubstitutionContext.Current = hookedContext; })); }