Getting the difficult stuff done using Typemock and xunit 2.0
I like Typemock - we should never have to change code to make it testable.
Mocking
To mock all static methods of a type
Isolate.Fake.StaticMethods(typeof(ClassName));
You will have problems sometimes especially if any class has a static constructor. Took me hours to figure out this below is a good idea before making the above call:
Isolate.Fake.StaticConstructor(typeof(ClassName));
Isolate.Invoke.StaticConstructor(typeof(ClassName)); >> Do not invoke this if you are going to swap instances which will internally attempt to call this.Isolate.Fake.StaticMethods(typeof(ClassName));
Calling original static method if above is done
Isolate.WhenCalled(() => ClassName.MethodName()).CallOriginal();
Mock the next instance of a certain type used within a method
var mockInstance = Isolate.Swap.NextInstance<ClassName>().WithRecursiveFake();
Isolate.WhenCalled(() => mockInstance.MethodName(null)).IgnoreCall();
Changing Behavior
Mock public static property of a type
Isolate.Fake.StaticMethods(typeof(ClassName));
Isolate.WhenCalled(() => ClassName.PropertyName).WillReturn(false);
Read value of private static field of a type
ObjectState.GetField(typeof(ClassName), "_fieldName").Should().Be(false);
Change behavior of private static methods within a type
Isolate.Fake.StaticMethods(typeof(ClassName)); Isolate.NonPublic.WhenCalled(typeof(ClassName), "MethodName").DoInstead(context => { skipped = false; });
Set output parameter for private static method within a type and not invoke it
Isolate.Fake.StaticMethods(typeof(ClassName)); Isolate.NonPublic.WhenCalled(typeof(ClassName), "MethodName").DoInstead(p =>
{
p.Parameters[1] = "key"; //output parameter
return true;
});
Set output parameter for private static method within a type and invoke it
var method = typeof(Folder).GetMethod("Method", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(int).MakeByRefType(), typeof(string) }, null);
int parameter = 1;
var parameters = new object[] { parameter, "name" };
var result = (bool) method.Invoke(object, parameters);
Change return value of private static method of a type
Isolate.NonPublic.WhenCalled(typeof(ClassName), "MethodName").WillReturn("string");
Changing return value of a private instance method
var mockObject = Isolate.Fake.Instance<ClassName>(Members.CallOriginal);
Isolate.NonPublic.WhenCalled(mockObject, "MethodName").WillReturn(false);
Change return value and internal behavior of a public instance method
var mockObject = Isolate.Swap.NextInstance<ClassName>().WithRecursiveFake();
Isolate.WhenCalled(() => mockObject.MethodName()).DoInstead(p => { callCounter.CallCount++; return 10; });
Change Value of a private field within an instance
var mockInstance = Isolate.Fake.Instance<ClassName>(Members.CallOriginal);
ObjectState.SetField(mockInstance, "_privatefield", Isolate.Fake.Instance<AnotherClassName>(Members.ReturnRecursiveFakes));
Unit Tests
Pass different values to parameter of test case method (xunit)
[Theory]
[InlineData("parameter value 1")]
[InlineData("parameter value 2")]
[InlineData("parameter value 3")]
[InlineData("parameter value 4")]
public void MethodName_WhenCondition_ShouldHappen(string parameter)
Pass different values to parameter of test case method (MSTestFramework)
[DataTestMethod]
[DataRow("parameter value 1")]
[DataRow("parameter value 2")]
[DataRow("parameter value 3")]
[DataRow("parameter value 4")]
public void MethodName_WhenCondition_ShouldHappen(string parameter)
Check if Exception is thrown by design
System.Action work = delegate { work(); };
work.ShouldThrow<InvalidOperationException>().WithMessage("some message");
Isolate.WhenCalled(() => instance.Method(user)).WillThrow(new MyException());
Invoke Private Method of Instance
Isolate.Invoke.Method(instance, "MethodName", parameter);
Verify Non Public Method was Called
Isolate.Verify.NonPublic.WasCalled(instance, "MethodName");
Inline Create items within Dictionary
var todoList = new SortedList<string, MyClass>() { { "key", Isolate.Fake.Instance<MyClass>(Members.ReturnRecursiveFakes) } };
xunit & TypeMock Gotchas
xunit runs tests in parallel, and the way typemock is injected into the framework classes, you might need to use the collection attribute for the unit test class to specify that tests which use the same code internally do not cause each other to fail by running in parallel:
https://xunit.github.io/docs/running-tests-in-parallel.html
[Collection("My Test Collection")]
[Isolated]
public class MyClassUnitTests
Mocking
To mock all static methods of a type
Isolate.Fake.StaticMethods(typeof(ClassName));
You will have problems sometimes especially if any class has a static constructor. Took me hours to figure out this below is a good idea before making the above call:
Isolate.Fake.StaticConstructor(typeof(ClassName));
Isolate.Invoke.StaticConstructor(typeof(ClassName)); >> Do not invoke this if you are going to swap instances which will internally attempt to call this.Isolate.Fake.StaticMethods(typeof(ClassName));
Calling original static method if above is done
Isolate.WhenCalled(() => ClassName.MethodName()).CallOriginal();
Mock the next instance of a certain type used within a method
var mockInstance = Isolate.Swap.NextInstance<ClassName>().WithRecursiveFake();
Isolate.WhenCalled(() => mockInstance.MethodName(null)).IgnoreCall();
Changing Behavior
Mock public static property of a type
Isolate.Fake.StaticMethods(typeof(ClassName));
Isolate.WhenCalled(() => ClassName.PropertyName).WillReturn(false);
Read value of private static field of a type
ObjectState.GetField(typeof(ClassName), "_fieldName").Should().Be(false);
Change behavior of private static methods within a type
Isolate.Fake.StaticMethods(typeof(ClassName)); Isolate.NonPublic.WhenCalled(typeof(ClassName), "MethodName").DoInstead(context => { skipped = false; });
Set output parameter for private static method within a type and not invoke it
Isolate.Fake.StaticMethods(typeof(ClassName)); Isolate.NonPublic.WhenCalled(typeof(ClassName), "MethodName").DoInstead(p =>
{
p.Parameters[1] = "key"; //output parameter
return true;
});
Set output parameter for private static method within a type and invoke it
var method = typeof(Folder).GetMethod("Method", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(int).MakeByRefType(), typeof(string) }, null);
int parameter = 1;
var parameters = new object[] { parameter, "name" };
var result = (bool) method.Invoke(object, parameters);
Change return value of private static method of a type
Isolate.NonPublic.WhenCalled(typeof(ClassName), "MethodName").WillReturn("string");
Changing return value of a private instance method
var mockObject = Isolate.Fake.Instance<ClassName>(Members.CallOriginal);
Isolate.NonPublic.WhenCalled(mockObject, "MethodName").WillReturn(false);
Change return value and internal behavior of a public instance method
var mockObject = Isolate.Swap.NextInstance<ClassName>().WithRecursiveFake();
Isolate.WhenCalled(() => mockObject.MethodName()).DoInstead(p => { callCounter.CallCount++; return 10; });
Change Value of a private field within an instance
var mockInstance = Isolate.Fake.Instance<ClassName>(Members.CallOriginal);
ObjectState.SetField(mockInstance, "_privatefield", Isolate.Fake.Instance<AnotherClassName>(Members.ReturnRecursiveFakes));
Unit Tests
Pass different values to parameter of test case method (xunit)
[Theory]
[InlineData("parameter value 1")]
[InlineData("parameter value 2")]
[InlineData("parameter value 3")]
[InlineData("parameter value 4")]
public void MethodName_WhenCondition_ShouldHappen(string parameter)
Pass different values to parameter of test case method (MSTestFramework)
[DataTestMethod]
[DataRow("parameter value 1")]
[DataRow("parameter value 2")]
[DataRow("parameter value 3")]
[DataRow("parameter value 4")]
public void MethodName_WhenCondition_ShouldHappen(string parameter)
Check if Exception is thrown by design
System.Action work = delegate { work(); };
work.ShouldThrow<InvalidOperationException>().WithMessage("some message");
Isolate.WhenCalled(() => instance.Method(user)).WillThrow(new MyException());
Invoke Private Method of Instance
Isolate.Invoke.Method(instance, "MethodName", parameter);
Verify Non Public Method was Called
Isolate.Verify.NonPublic.WasCalled(instance, "MethodName");
Inline Create items within Dictionary
var todoList = new SortedList<string, MyClass>() { { "key", Isolate.Fake.Instance<MyClass>(Members.ReturnRecursiveFakes) } };
xunit & TypeMock Gotchas
xunit runs tests in parallel, and the way typemock is injected into the framework classes, you might need to use the collection attribute for the unit test class to specify that tests which use the same code internally do not cause each other to fail by running in parallel:
https://xunit.github.io/docs/running-tests-in-parallel.html
[Collection("My Test Collection")]
[Isolated]
public class MyClassUnitTests
Comments
Post a Comment