chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
We have a mix of tests that use and don't use Typemock.

We use Typemock 8.0.5.2, xUnit 2.0, Visual Studio 2013.

Since updating, I am finding that tests have become unpredictable. Some tests that don't even use typemock at all, and aren't even annotated with the [Isolate] attribute are failing when Typemock is running. If I uncheck "Integrate with other runners" suddenly they start passing.

I will post some stacks as comments.
asked by Jahmai (2.8k points)
Here's one stack (removed some Async stuff so it fit in the 8000 character limit)
 
 
System.IO.IOExceptionAuthentication failed because the remote party has closed the transport stream.
   at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsServer(IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Streams.IO.XIOStream.<StarttlsAsyncCore>d__32.MoveNext() in XIOStream.cs: line 575
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Protocols.Core.Starttls.XStarttlsReceiver.<NegotiateAsyncCore>d__1.MoveNext() in XStarttlsReceiver.cs: line 74
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Streams.XReceiverStream.<NegotiateProtocolsAsyncCore>d__13.MoveNext() in XReceiverStream.cs: line 257
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Streams.XReceiverStream.<OpenAsyncCore>d__19.MoveNext() in XReceiverStream.cs: line 315
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Streams.IO.XIOReceiverStream.<OpenAsyncCore>d__28.MoveNext() in XIOReceiverStream.cs: line 116
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Streams.XStream.<OpenAsyncInternal>d__16.MoveNext() in XStream.cs: line 158
--- End of stack trace from previous location where exception was thrown ---
   at CriticalArc.SafeZoneApp.SaslCredentialsProviderTests.<<ClearCredentialsDoesNotFireUnobservedException>b__0>d__2.MoveNext() in SaslCredentialsProviderTests.cs: line 53
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.AssertTester.<DoesNotFireUnobservedExceptionAsync>d__6.MoveNext() in AssertTester.cs: line 74
--- End of stack trace from previous location where exception was thrown ---
   at CriticalArc.SafeZoneApp.SaslCredentialsProviderTests.<ClearCredentialsDoesNotFireUnobservedException>d__b.MoveNext() in SaslCredentialsProviderTests.cs: line 40
--- End of stack trace from previous location where exception was thrown ---
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClassc.<<InvokeTestMethodAsync>b__9>d__e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Xunit.Sdk.ExecutionTimer.<AggregateAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Xunit.Sdk.ExceptionAggregator.<RunAsync>d__0.MoveNext() in c:TeamCityuildAgentwork<856245f07a90f0srcxunit.coreSdkExceptionAggregator.cs: line 90
 
 

 

System.MissingMethodExceptionMethod not found: 'Void TypeMock.Interceptors.StreamWriterInterceptor..ctor(System.IO.Stream, System.Text.Encoding, Int32, Boolean)'.
   at Intrinsic.Diagnostics.RollingFlatFileTracerListener.CountingStreamWriter..ctor(Stream stream)
   at Intrinsic.Diagnostics.RollingFlatFileTracerListener.<.ctor>b__2() in RollingFlatFileTracerListener.cs: line 84
   at Intrinsic.DisposeScope.Add(Func`1 allocator, Action`1[] actions) in DisposeScope.cs: line 113
   at Intrinsic.Diagnostics.RollingFlatFileTracerListener..ctor(RollingFlatFileTracerListenerSettings settings) in RollingFlatFileTracerListener.cs: line 84
   at Intrinsic.Diagnostics.RollingFlatFileTracerListener..ctor(String fileName) in RollingFlatFileTracerListener.cs: line 54
   at Intrinsic.Diagnostics.RollingFlatFileTracerListenerTests.Append() in RollingFlatFileTracerListenerTests.cs: line 35
 
System.MissingMethodExceptionMethod not found: 'Void TypeMock.Interceptors.BinaryWriterInterceptor..ctor(System.IO.Stream, System.Text.Encoding, Boolean)'.
   at Intrinsic.IO.BytesBinaryWriter..ctor(BytesMemoryStream output, Encoding encoding, Boolean leaveOpen)
   at Intrinsic.IO.IBinaryExtensions.Write(IBinary binary, BytesMemoryStream stream) in IBinaryExtensions.cs: line 51
   at Intrinsic.Net.Security.Tls.TlsStream.<SendAsyncCore>d__29.MoveNext() in TlsStream.cs: line 696
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Intrinsic.Net.Security.Tls.TlsClientStream.<AuthenticateAsyncCore>d__40.MoveNext() in TlsClientStream.cs: line 128
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Intrinsic.AssertTester.<IsRanToCompletionAsync>d__15.MoveNext() in AssertTester.cs: line 366
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Intrinsic.Net.Security.Tls.TlsClientStreamTests.<Authenticate>d__3.MoveNext() in TlsClientStreamTests.cs: line 38
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClassc.<<InvokeTestMethodAsync>b__9>d__e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Xunit.Sdk.ExecutionTimer.<AggregateAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Xunit.Sdk.ExceptionAggregator.<RunAsync>d__0.MoveNext() in c:TeamCityuildAgentwork<856245f07a90f0srcxunit.coreSdkExceptionAggregator.cs: line 90
 
TypeMock.TypeMockException
*** No method calls found in recording block. Please check:
 * Are you trying to fake a field instead of a property?
 * Are you are trying to fake an unsupported mscorlib type? See supported types here: https://www.typemock.com/mscorlib-types
   at TypeMock.ArrangeActAssert.BehaviorRecordingEngine.StoreAdditionalInformationHook(RecordingScopeBase scope, Boolean checkForEmptyRecordingBlock)
   at TypeMock.ArrangeActAssert.RecordingEngineBase.Record(Boolean checkForEmptyRecordingBlock)
   at TypeMock.ArrangeActAssert.RecorderBase.InvokeAndRecord(Boolean checkForEmptyRecordingBlock)
   at TypeMock.ArrangeActAssert.ExpectationEngine.RecordCallAndLoadResults(Boolean shouldCheckForEmptyRecordingBlock)
   at TypeMock.ArrangeActAssert.ExpectationEngine.PerformCompletingStatement(Object toReturn, Boolean isException, Func`1 performEarlyExit, Action conditionalAction, Action defaultAction, Action beforeExit, Boolean shouldCheckForEmptyRecordingBlock)
   at TypeMock.ArrangeActAssert.ExpectationEngine.WillReturn(Object value)
   at TypeMock.ArrangeActAssert.ExpectationEngine`1.WillReturn(TResult value)
   at Intrinsic.Messaging.Streams.IO.XIOBufferedStreamTests.<DelayedFlushAsync>d__10.MoveNext() in XIOBufferedStreamTests.cs: line 48
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClassc.<<InvokeTestMethodAsync>b__9>d__e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Xunit.Sdk.ExecutionTimer.<AggregateAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Xunit.Sdk.ExceptionAggregator.<RunAsync>d__0.MoveNext() in c:TeamCityuildAgentwork<856245f07a90f0srcxunit.coreSdkExceptionAggregator.cs: line 90
 

4 Answers

0 votes
 
Best answer

Hi Jahmai,

About the public static readonly variables are null during mocking.

This is expected as we don't call the static constructor in the WhenCalled lamda. This is because everything is Faked in the WhenCalled. And thus the field is null (if this was a method - it would be faked)

So simplly invoke the static constructor before faking:













[TestClassIsolated]
     public class TypeMockTests
     {         
         [TestMethod]
         public static void PublicStaticReadOnlyAreNotNull()
         {
             Isolate.Invoke.StaticConstructor<Faked>();
             Isolate.WhenCalled(() => Faked.Instance.Method()).IgnoreCall();
         }         private class Faked
         {             public static readonly Faked Instance = new Faked();
             public void Method()
             {
             }
         }
     }
answered by Bar (3.3k points)
selected by Jahmai

I'm afraid my example was overly simple.

I believe I've discovered the issue. I was too quick to confirm async tests were fixed. The problem I'm seeing now is that Isolate.Cleanup is still being called too soon and a bunch of static variables are being nulled. This is happening to classes within the tests that aren't being faked. Looking into the disassembly I see:

        using (MockManager._2VOu5Q6V7dYszYg1YsPzuPoCA6H_(this._jP5iprAeXReWLPFfMiSAj9fxlAq_()))
        {
          object obj = this.CallDecoratedMethod();
          if (obj != null && obj.GetType().Namespace == "System.Threading.Tasks" && obj.GetType().Name == "Task`1")
          {
            MethodInfo method = obj.GetType().GetMethod("Wait", new Type[0]);
            if (method != null)
              method.Invoke(obj, new object[0]);
          }
          return obj;
        }

I believe the issue is 'obj.GetType().Name == "Task`1"'. "Task`1" is the name of the generic Task<> type. Since tests don't have a return value, you want the non-generic version which is simply "Task".

 

Still looking into this?
Hi Jahmi,

 

Please download the following patch to confitm that this issue is fixed:

www.typemock.com/files/patches/TypemockIsolatorClient_Jahmi_GenericTask.msi

 

If it is, we'll include it in our next release.
I'm afraid I can't get it to work. Visual studio throws an error when opening about an extension failing to load and the TypeMock menu item is not present.

I've tried uninstalling and installing, and then I uninstalled, search and deleted all entries I could find relating to TypeMock in the registry and installing again, but the problem persists.
We're about to release a version that includes this fix.

I'll update you ASAP

Hi,

We released a version with this fix.

Please install it and let us know if it helps.

I had to run devenv.exe to fix my extension issue.

Now we're getting this error:

c:TeamCityuildAgentwork<856245f07a90f0srcxunit.coreSdkExceptionAggregator.cs: line 90
System.ArgumentExceptionAn item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at TypeMock.Internal.StaticConstructorsHandler.AddInvokedCCtor(String typeName)
   at TypeMock.MockManager.isMocked(Object context, String typeName, String methodName, Object methodParameters, Boolean isDecorated, Boolean isIntercepted)
   at Typemock.Interceptors.Profiler.InternalMockManager.isMocked(Object that, String typeName, String methodName, Object methodParameters, Boolean isInjected, Boolean isIntercepted)
Here is the stack:
System.TypeInitializationExceptionThe type initializer for 'TracerFor`1' threw an exception.
   at Intrinsic.Diagnostics.Tracer.For(T instance, String memberName, String filePath, Int32 lineNumber) in Tracer.cs: line 61
   at Intrinsic.Messaging.Streams.IO.XIOStream.WriteStreamOpenAsync(XStreamHeader streamHeader, AsyncOptions asyncOptions) in XIOStream.cs: line 743
   at Intrinsic.Messaging.Streams.IO.XIOInitiatorStream.WriteStreamOpenAsyncCore(XStreamHeader streamHeader, AsyncOptions asyncOptions) in XIOInitiatorStream.cs: line 183
   at Intrinsic.Messaging.Streams.XProtocolStream.WriteStreamOpenAsyncInternal(XStreamHeader streamHeader, AsyncOptions asyncOptions) in XProtocolStream.cs: line 352
   at Intrinsic.Threading.Tasks.TracerExtensions.<>c__DisplayClass13`1.<Async>b__12(AsyncOptions asyncOptions2) in TracerExtensions.cs: line 192
   at Intrinsic.Threading.Tasks.TracerExtensions.AsyncCore(Tracer tracer, Func`2 function, AsyncOptions asyncOptions, String methodName) in TracerExtensions.cs: line 812
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Streams.XInitiatorStream.<OpenAsyncCore>d__2c.MoveNext() in XInitiatorStream.cs: line 266
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Streams.IO.XIOInitiatorStream.<OpenAsyncCore>d__3a.MoveNext() in XIOInitiatorStream.cs: line 115
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Streams.XStream.<OpenAsyncInternal>d__16.MoveNext() in XStream.cs: line 158
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Connectors.XTcpConnector.XRedirectableStream.<OpenAsyncCore>d__12.MoveNext() in XTcpConnector.cs: line 234
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Streams.XStream.<OpenAsyncInternal>d__16.MoveNext() in XStream.cs: line 158
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Connectors.XTcpConnectorTests.<>c__DisplayClass16.<<Redirect>b__d>d__18.MoveNext() in XTcpConnectorTests.cs: line 79
--- End of stack trace from previous location where exception was thrown ---
   at Intrinsic.Messaging.Connectors.XTcpConnectorTests.<Redirect>d__23.MoveNext() in XTcpConnectorTests.cs: line 75
--- End of stack trace from previous location where exception was thrown ---
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClassc.<<InvokeTestMethodAsync>b__9>d__e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Xunit.Sdk.ExecutionTimer.<AggregateAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Xunit.Sdk.ExceptionAggregator.<RunAsync>d__0.MoveNext() in c:TeamCityuildAgentwork<856245f07a90f0srcxunit.coreSdkExceptionAggregator.cs: line 90
System.ArgumentExceptionAn item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at TypeMock.Internal.StaticConstructorsHandler.AddInvokedCCtor(String typeName)
   at TypeMock.MockManager.isMocked(Object context, String typeName, String methodName, Object methodParameters, Boolean isDecorated, Boolean isIntercepted)
   at Typemock.Interceptors.Profiler.InternalMockManager.isMocked(Object that, String typeName, String methodName, Object methodParameters, Boolean isInjected, Boolean isIntercepted)
   at Intrinsic.Diagnostics.Tracer.TracerFor`1..cctor() in Tracer.cs: line 492
 
Tracer is our class that looks like this:
 
        private static class TracerFor<T>
        {
            public static readonly Tracer Instance = new Tracer(typeof(T),
                                                                TracerSource.Global,
                                                                TracerSource.ForAssembly<T>(),
                                                                TracerSource.ForNamespace<T>(),
                                                                TracerSource.ForType<T>());
        }

 

Seems like Typemock tracks static constructors internally and doesn't correctly deal with static constructors on generic types?

So in summary, TypeMock has been unusuable for us since upgrading to v8.

Just about out of patience.
0 votes
Hi Jahmai,

Thank you for informing us of these issues.

We fixed BinaryWriter ans StreaWriter issues, the fix will be available in our next version (8.1).

we'll send you a patch tomorrow to confirm.

Please advise on how to reproduce all others. maybe you can share the tests that fail?
answered by alex (17k points)
I have done further investigations and found that a couple of these issues stem from the BinaryWriter problem.

I do have another bizarre one though which I don't even know how to explain except that it has something to do with the attribute we use to mark tests. We inherit from FactAttribute in Xunit and call it TestAttribute and mark our tests with [Test]. If i replace [Test] with [Fact] it fixes the tests. Even weirder is if I create another attribute called MyFactAttribute and mark them with [MyFact] it also fixes the tests.

I have a solution exhibiting the problem. How can I get it to you?

What appears to be happening here is:

1. Typemock does't properly support async test methods with mocking, which means as soon as there is an "await", the test method returns an incomplete Task and Typemock regards the test as finished.

2. Methods are decorated with executors but are not "decorated" by default unless they have an attribute named "TestAttribute" (MethodBaseExtensions.IsTestMethod), otherwise you need to implement a Decorator and override DecorateMethodWhenAttributeIsClass.

3. Since the methods decorated with "FactAttribute" and "MyFactAttribute" are not decorated, they do not perform Isolate.Cleanup(?), which means the async method can keep running without issues after the test returns an incomplete task.

4. Since "TestAttribute" is decorated, Isolate.Cleanup *is* called, which means that the mocks established during the test are torn down before the async method has completed. Then when the async method continues execution and attempts to assert something like Isolate.WhenCalled, it throws an exception that it can't find the mocked method, causing the issue.

This is actually pretty enlightening. Previously we worked around this on async methods by manually calling Isolate.Cleanup (in a hander disposable wrapper class).

Now that I know this, I can fix this with:

 

    [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, Inherited = false)]
    public sealed class AsyncAttribute : DecoratorAttribute
    {
        #region Methods
        protected override bool DecorateMethodWhenAttributeIsClass(MethodBase methodBase)
        {
            return true;
        }

        public override object Execute()
        {
            object result = CallDecoratedMethod();
            Task task = (result as Task);

            if (task != null)
                task.Wait();

            return result;
        }
        #endregion
    }

 

And apply it to all classes that have [Isolated]. Any problems with this approach?

Actually the above code won't work because the Isolate attribute has already called Cleanup.

Why is it so hard, TypeMock? :)

OK, so since Isolate.Cleanup can be called inside IsolateAttribute.Execute, I went ahead and did this:

[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, Inherited = false)]
public sealed class AsyncIsolatedAttribute : IsolatedAttribute
{
	#region Static Fields
	private static readonly MethodInfo DecoratorAttributeSendTestNameToTracerMethodInfo
		= typeof(AsyncIsolatedAttribute).GetMethod("SendTestNameToTracer", BindingFlags.NonPublic | BindingFlags.Instance);

	private static readonly FieldInfo ExceptionRemoteStackStringFieldInfo
		= typeof(Exception).GetField("_remoteStackTraceString", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly MethodInfo IsolateCleanUpMethodInfo
		= typeof(Isolate).GetMethod("CleanUp", BindingFlags.NonPublic | BindingFlags.Static);

	private static readonly MethodInfo IsolatedAttributeGetStrictFlagMethodInfo
		= typeof(IsolatedAttribute).GetMethod("GetStrictFlag", BindingFlags.NonPublic | BindingFlags.Instance);

	private static readonly MethodInfo MockManagerTestModeMethodInfo
		= typeof(MockManager).GetMethod("TestMode", BindingFlags.NonPublic | BindingFlags.Static);

	private static readonly MethodInfo SuggestBehaviorSetArmadilloTestsMethodInfo
		= typeof(MockManager).Assembly.GetType("TypeMock.SuggestBehavior").GetMethod("SetArmadilloTests", BindingFlags.Public | BindingFlags.Static);

	private static readonly List<string> TestAttributes = new List<string>
														  {
															  "TestAttribute",
															  "DataTestAttribute",
															  "FactAttribute",
															  "TheoryAttribute",
														  };
	#endregion

	#region Methods
	protected override bool DecorateMethodWhenAttributeIsClass(MethodBase methodBase)
	{
		foreach (object attribute in methodBase.GetCustomAttributes(false))
		{
			if (TestAttributes.Contains(attribute.GetType().Name))
				return true;
		}

		return base.DecorateMethodWhenAttributeIsClass(methodBase);
	}

	public override object Execute()
	{
		if (!IsTearDown)
		{
			if (!MockManager.IsInitialized)
				MockManager.Init();

			Type declaringType = OriginalMethod.DeclaringType;
			bool isArmadillo = (declaringType != null && declaringType.Assembly.IsDefined(typeof(SuggestBehaviorAttribute), false));

			SuggestBehaviorSetArmadilloTestsMethodInfo.Invoke(null, new object[] { isArmadillo });
			DecoratorAttributeSendTestNameToTracerMethodInfo.Invoke(this, null);

			if (declaringType != null)
			{
				if (declaringType.IsDefined(typeof(SafetyNetAttribute), true))
				{
					SafetyNetAttribute safetyNetAttribute = (SafetyNetAttribute)declaringType.GetCustomAttributes(typeof(SafetyNetAttribute), true)[0];

					if (safetyNetAttribute != null)
					{
						if (safetyNetAttribute.Sandbox)
							TestUtil.AssertRunningInSandbox();
					}
				}
			}
		}

		try
		{
			using ((IDisposable)MockManagerTestModeMethodInfo.Invoke(null, new[] { IsolatedAttributeGetStrictFlagMethodInfo.Invoke(this, null) }))
			{
				object result = CallDecoratedMethod();
				Task task = (result as Task);

				if (task != null)
					task.Wait();

				return result;
			}
		}
		catch (TargetInvocationException ex)
		{
			ExceptionRemoteStackStringFieldInfo.SetValue(ex.InnerException, ex.InnerException.StackTrace + Environment.NewLine);
			ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
			throw;
		}
		finally
		{
			IsolateCleanUpMethodInfo.Invoke(null, new object[] { !HasTearDown || IsTearDown, IgnoreStaleMocks });
		}
	}
	#endregion
}

But then I found that this Execute isn't called. Turns out the framework only does it if there are other decorators. So then I made this:

[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, Inherited = false)]
public sealed class EmptyDecoratorAttribute : DecoratorAttribute
{
	#region Static Fields
	private static readonly List<string> TestAttributes = new List<string>
														  {
															  "TestAttribute",
															  "DataTestAttribute",
															  "FactAttribute",
															  "TheoryAttribute",
														  };
	#endregion

	#region Methods
	protected override bool DecorateMethodWhenAttributeIsClass(MethodBase methodBase)
	{
		Validate.Argument.IsNotNull("methodBase", methodBase);

		foreach (object attribute in methodBase.GetCustomAttributes(false))
		{
			if (TestAttributes.Contains(attribute.GetType().Name))
				return true;
		}

		return base.DecorateMethodWhenAttributeIsClass(methodBase);
	}

	public override object Execute()
	{
		return CallDecoratedMethod();
	}
	#endregion
}

Now on my tests I can do:

[AsyncIsolated]
[EmptyDecorator]
[Collection("Isolated")]
public sealed class MyTests
{
	public async Task MyAsyncTest()
	{
		// Mocking and await work fine
	}
}

AsyncIsolated ensures that the Task is waited upon before Cleanup is called. EmptyDecorator ensures that AsyncIsolated is actually used. Collection is an xUnit 2 attribute that stops classes in the "Isolated" collection from running concurrently.

With this, our async tests work great in Typemock 8.0.5.2, xUnit 2, Resharper 9.1 and Visual Studio 2013.

But really TypeMock, support async by default please!

Let me know when the patch for BinaryWriter / StreamWriter are ready since we still have that problem.

Any update on that patch?
I've updated to 8.1.0.17.

First, my trick above doesn't work anymore due to the obfuscation which is annoying (little late now that 8.0.5.2 was released without it, dontchya think?), but I found another way.

Second, there are still issues with BinaryWriter at the least. We have a custom class that extends BinaryWriter. We create it and it calls the BinaryWriter constructor with the "leaveOpen" parameter set to true. This means that you can dispose the BinaryWriter but it doesn't dispose the inner stream. However, with TypeMock enabled, it always disposes the inner stream, which breaks all our IO tests that use BinaryWriter and require the stream to stay open.

Let me know if you need code to reproduce it, but it's pretty straight forward.

I see you've pulled 8.1 from download.

To be clear, this test demonstrates the problem:

    public class TypeMockTests
    {
        #region Methods
        [Fact]
        public void BinaryWriterDoesNotDisposeInnerStreamWhenLeftOpen()
        {
            MemoryStream stream = new MemoryStream();

            // Doesn't throw
            stream.Write(new byte[0], 0, 0);

            using (new BinaryWriter(stream, Encoding.UTF8, true))
            {
            }

            // Shouldn't throw
            stream.Write(new byte[0], 0, 0);
        }
        #endregion
    }

 

8.1.1.3 still has this issue.

Can someone other than me update this question with some progress / feedback please?
Hi Jahmai,

Sorry for the late reply.

We're aware of the issue that followed our fix.

We're currently working on it, I'll update you ASAP.
Thanks Alex, I'll await your update before trying new releases.
0 votes
Hi,

We have managed to isolate and fix these issues. It should be ready in a few days.

In this fix we will.

1. Support mstest async in SmartRunner
2. Support clearing fakes after async method completed
3. Return a default fake value for all recursive fake async methods.
4. Added support for xunit attributes

5. we have also fixed the BinaryWriter bug.

Thanks for the code examples for the decorators.
answered by eli (5.7k points)
Hi Eli,

Will this fix also address the issue I mentioned in this question https://www.typemock.com/answers/19124/methodaccessexception-when-unit-test-sets-content-label-wpf?

Thanks in advance,

Carlos
Sounds great Eli, looking forward to it.
0 votes

Hi,

We fixed this issue in version 8.1.1.8 .

You can download it from here.

 

answered by Bar (3.3k points)
I can only download 8.1.1.9. The installer is only 1.4MB and complains about being invalid when I try to run it.

Installed 8.1.1.10.

Confirmed that both the BinaryWriter and Async test issues are fixed, but...

Regression;

public static readonly variables are null during mocking. Here is a test that demonstrates this issue:

[Isolated]
public class TypeMockTests
{
  [Fact]
  public static void PublicStaticReadOnlyAreNotNull()
  {
      // Faked.Instance.Method() throws NullReferenceException due to Faked.Instance being null
      Isolate.WhenCalled(() => Faked.Instance.Method()).IgnoreCall();
  }

  private class Faked
  {
    public static readonly Faked Instance = new Faked();

    public void Method()
    {
    }
  }
}

Here is the output of the test:

TypeMock.TypeMockException
*** No method calls found in recording block. Please check:
 * Are you trying to fake a field instead of a property?
 * Are you are trying to fake an unsupported mscorlib type? See supported types here: https://www.typemock.com/mscorlib-types
   at _4fOddA7JgGYbOOebRdG4fQREBGkb_._aNtnIwgxjLwUpminjJDGdVtHBTH_._eAtw4rxkQILc50tjMfFmPOUwIJo_(Boolean)
   at _4fOddA7JgGYbOOebRdG4fQREBGkb_._nzVsxF4j04UocypgyEFRFXQby0w_._R6XuDLwlccMpAxcdUJbImOBbMW4b_(Boolean)
   at _4fOddA7JgGYbOOebRdG4fQREBGkb_._nzVsxF4j04UocypgyEFRFXQby0w_._3P6pfP7t5yKdJIrbbfQKhqsDfAu_(Object, Boolean, Func`1, Action, Action, Action, Boolean)
   at _4fOddA7JgGYbOOebRdG4fQREBGkb_._nzVsxF4j04UocypgyEFRFXQby0w_._3P6pfP7t5yKdJIrbbfQKhqsDfAu_(Object, Boolean, Action, Action)
   at _4fOddA7JgGYbOOebRdG4fQREBGkb_._nzVsxF4j04UocypgyEFRFXQby0w_.IgnoreCall()
   at TypeMock.MockManager.getReturn(Object context, String typeName, String methodName, Object methodGenericParams, Boolean isDecorated, Boolean isInterceptedType, Object[] methodArguments)
   at Typemock.Interceptors.Profiler.InternalMockManager.getReturn(Object that, String typeName, String methodName, Object methodParameters, Boolean isInjected, Boolean isInterceptedType)
   at Intrinsic.TypeMock.TypeMockTests.PublicStaticReadOnlyAreNotNull() in TypeMockTests.cs: line 41
 
Here is the exception stack if you break on NullReferenceException and debug the test:
 
System.NullReferenceException occurred
  _HResult=-2147467261
  _message=Object reference not set to an instance of an object.
  HResult=-2147467261
  IsTransient=false
  Message=Object reference not set to an instance of an object.
  Source=Intrinsic.Core.Tests
  StackTrace:
       at Intrinsic.TypeMock.TypeMockTests.<PublicStaticReadOnlyAreNotNull>b__6() in c:RepositoryProjectsCriticalArcDependenciesIntrinsicTestsLibrariesCoreTypeMockTypeMockTests.cs:line 41
  InnerException: 
 

This problem still exists in 8.1.1.11

Can someone please update this question with some progress? TypeMock has been royally broken for us for a few weeks now.
Sorry for the late reply.

We're currently working on it, I'll update you ASAP.
...