Combination of Moq and Equals() crashing the MS Testing framework - c#

I have what I think should be a very simple test case, but every time I run it QTAgent32 dies. Running the test case in Debug mode shows a System.StackOverflowException being thrown in 'Unknown Module'. I've narrowed it down to the most basic implementation that exhibits this behavior (.NET 4 and VS 2010 Ultimate):
[TestClass]
public class StackOverflow
{
[TestMethod]
public void CreateStackOverflow()
{
var mockMyType1 = new Mock<MyType>();
mockMyType1.Setup(m => m.Equals(mockMyType1.Object)).Returns(true);
var mockMyType2 = new Mock<MyType>();
// Real test is for a filtering routine and the Assert is using
// Contains(), but it uses Equals() internally so it has the same problem
Assert.IsTrue(mockMyType1.Object.Equals(mockMyType1.Object)); // returns true
Assert.IsFalse(mockMyType1.Object.Equals(mockMyType2.Object)); // explodes
}
}
public class MyType
{
public virtual bool IsActive { get; set; }
public override bool Equals(object obj)
{
return false; // Not the real implementation but irrelevant to this issue
}
}
I feel like I'm missing something important about closures or maybe Moq, but it seems like this should work. Things I have tried, attempting to understand the issue, but have only confused me more:
I tried replacing the Equals() setup with mockMyType.Setup(m => m.Equals(m)).Returns(true); but that causes Moq to throw an NotSupportedException
If I make CallBase true instead of setting up Equals(), everything works
Finally, if the MyType class doesn't override Equals(), everything works.
Can anyone point me in the direction of what might be happening? I'm completely at a loss.
Edit: I believe I have a couple of options for making this work (including Lanorkin's response below), but I'd really like to know why this is happening. Am I doing something wrong or is there a bug in Moq or Visual Studio that I should be submitting?
Update: I ended up going with a version of Denys solution below and filing a bug report to Moq. My setup now looks like:
mockMyType1.Setup(m => m.Equals(It.Is<MyType>(x => ReferenceEquals(x, mockMyType1.Object)))).Returns(true);

Yes, mocking Equals(object) make it fail (use Reflector/dotPeek to see more):
Good news - it's easy to workaround. Just add Equals overload to MyType class, thus mocking Equals(MyType) instead of Equals(object):
public virtual bool Equals(MyType obj)
{
return Equals((object)obj);
}

This question disturbs me since yesterday and finally I found the answer. You have to use a function in your setup method and it should assert against real equality of the mock objects. What I mean is ReferenceEquals. So I modified your GetMockMyTypes code. Sure it can't be used as a reference but intent is clear so far:
public static class MyTypeHelper
{
public static IList<MyType> GetMockMyTypes()
{
var myTypes = new List<MyType>();
var myMock1 = new Mock<MyType>().Object;
Mock.Get(myMock1)
.Setup(m => m.Equals(It.Is<MyType>(x => ReferenceEquals(x, myMock1))))
.Returns(true);
Mock.Get(myMock1).Setup(m => m.IsActive).Returns(false);
myTypes.Add(myMock1);
var myMock2 = new Mock<MyType>().Object;
Mock.Get(myMock2)
.Setup(m => m.Equals(It.Is<MyType>(x => ReferenceEquals(x, myMock2))))
.Returns(true);
Mock.Get(myMock2).Setup(m => m.IsActive).Returns(true);
myTypes.Add(myMock2);
return myTypes;
}
}

I think the issue is that you do:
mockMyType.Setup(m => m.Equals(mockMyType.Object)).Returns(true);
which only mocks against parameter of that same object. If you use any other parameter it will not get matched.
Please try to do this instead:
mockMyType.Setup(m => m.Equals(It.IsAny<MyType>())).Returns(true);
However, you should get a different exception about unexpected method call.

Related

Moq: Using the CallBase() for a method with parameters and a return value to perfrom the original behavior of the method

I wanted one method in mocked object to perfrom its original behavior and return a value by that behavior. But I could not make it.
The below is a sample code.
public interface IMyTest {
public StringBuilder GetBuilder(string initial);
}
public class MyTest : IMyTest {
public StringBuilder GetBuilder(string initial) {
return new StringBuilder(initial + initial);
}
}
[TestFixture]
public class MyTestTest {
[Test]
public void GetBuilderTest() {
Mock<IMyTest> obj = new() {
CallBase = true
};
obj.Setup(x => x.GetBuilder(It.IsAny<string>())).CallBase();
var a = obj.Object.GetBuilder("ABC");
TestContext.WriteLine(a.ToString());
}
}
So I have created a mock object of IMyTest, and wanted let the GetBuilder() method to do the actual original behavior of doubling the input string.
I thought the CallBase() is for such a purpose, but it raises an error like:
This is a DynamicProxy2 error: The interceptor attempted to 'Proceed' for method 'System.Text.StringBuilder GetBuilder(System.String)' which has no target. When calling method without target there is no implementation to 'proceed' to and it is the responsibility of the interceptor to mimic the implementation (set return value, out arguments etc)
Because I am still new to Moq, I might be misunderstanding, but could not find an answer by googling. So if you could kindly help on my question.
Of course, it can use the Return() with the same new StringBuilder(initial + initial) in it, but please think that method is doing very complex work inside of it actually that I do not want to mimic it manually.

Testing Optional equivalence with FluentAssertions

I'm using a library called Optional (https://github.com/nlkl/Optional) that allows the "maybe" abstraction that is common to functional languages.
The library is awesome, but I'm facing a problem regarding testing: I can't test correctly whether 2 optional instances are equivalent or not.
To test for equivalence I'm using Fluent Assertions. However, I'm not getting the desired results.
I will illustrate the problem with code:
#load "xunit"
[Fact]
void TestOptional()
{
var a = new[] { 1, 2, 3 }.Some();
var b = new[] { 1, 2, 3 }.Some();
a.Should().BeEquivalentTo(b);
}
This test fails, as I show in the screenshot (I'm using LINQPad, for convenience)
As you see, this isn't what one expects.
How do I tell Fluent Assertions to check the equivalence correctly using the Option type?
UPDATE
I opened an issue on Github regarding your problem and yesterday a pull request was merged, so the next (pre-)release should enable you to solve your problem elegantly:
The new overloads allows you to use an open generic type.
If both an open and closed type are specified, the closed type takes precedence.
SelfReferenceEquivalencyAssertionOptions adds the following methods:
public TSelf ComparingByMembers(System.Type type) { }
public TSelf ComparingByValue(System.Type type) { }
Here's the unit test that was added to Fluent Assertions showing how it works:
[Fact]
public void When_comparing_an_open_type_by_members_it_should_succeed()
{
// Arrange
var subject = new Option<int[]>(new[] { 1, 3, 2 });
var expected = new Option<int[]>(new[] { 1, 2, 3 });
// Act
Action act = () => subject.Should().BeEquivalentTo(expected, opt => opt
.ComparingByMembers(typeof(Option<>)));
// Assert
act.Should().NotThrow();
}
Fluent Assertions - Object Graph Comparison says:
Value Types
To determine whether Fluent Assertions should recurs into an object’s
properties or fields, it needs to understand what types have value
semantics and what types should be treated as reference types. The
default behavior is to treat every type that overrides Object.Equals
as an object that was designed to have value semantics. Unfortunately,
anonymous types and tuples also override this method, but because we
tend to use them quite often in equivalency comparison, we always
compare them by their properties.
You can easily override this by using the ComparingByValue<T> or
ComparingByMembers<T> options for individual assertions
Option<T> is a struct and overrides Equals, so Fluent Assertions compares a and b with value semantics.
Option<T> implements Equals like this:
public bool Equals(Option<T> other)
{
if (!this.hasValue && !other.hasValue)
return true;
return this.hasValue
&& other.hasValue
&& EqualityComparer<T>.Default.Equals(this.value, other.value);
}
Thus int[] is compared by reference and your test fails.
You can override this behavior for each test individually, like Guro Stron said:
a.Should().BeEquivalentTo(b, opt => opt.ComparingByMembers<Option<int[]>>());
Or globally via static AssertionOptions class:
AssertionOptions.AssertEquivalencyUsing(options =>
options.ComparingByMembers<Option<int[]>>());
edit:
For your case Fluent Assertions would need an AssertEquivalencyUsing override that supports unbound generic types:
AssertionOptions.AssertEquivalencyUsing(options =>
options.ComparingByMembers(typeof(Option<>)));
No such override exists, unfortunately.
Another solution a came up with would be an extension method. Here a very simplistic implementation:
public static class FluentAssertionsExtensions
{
public static void BeEquivalentByMembers<TExpectation>(
this ComparableTypeAssertions<TExpectation> actual,
TExpectation expectation)
{
actual.BeEquivalentTo(
expectation,
options => options.ComparingByMembers<TExpectation>());
}
}

Override ToString in NUnit without access to source code

I have a class, Foo, from a third party library that I check for equality against another instance using NUnit,
Assert.AreEqual(foo1, foo2);
When the objects are different I get the expected failure,
Expected: Foo
But was: Foo
But the error message isn't very helpful. I know NUnit uses ToString to show the error message but I can't override that here.
Does NUnit provide an API to override this behaviour so I can supply my own ToString implementation? I can't see anything on the Assert.AreEqual and Assert.That APIs
You can add specific formatting code for any Type and NUnit will use it. See https://github.com/nunit/docs/wiki/TestContext#addformatter
This feature was added in NUnit 3.2.
This may not be a great approach, but you could wrap the values inside of another class, and override ToString() there. For instance, in your test fixture, create the following private class:
private class ValueWrapper
{
private readonly OtherClass _wrapped;
public ValueWrapper(OtherClass wrapped)
{
_wrapped = wrapped;
}
public override bool Equals(object obj)
{
// Compare the wrapped objects for equality.
// This needs some beefing up for null checks, type checks, etc.
return _wrapped.Equals(obj._wrapped);
}
public override string ToString()
{
return "whatever you like";
}
}
With this wrapper class in hand, you could then wrap your expected & actual values and pass this into the asserts. For a CollectionAssert, you'd do so by transforming each element in the collection into one of these, using a Select() LINQ clause.
Using the accepted answer I put together the following code to json-serialize my failed constraints (using Json.NET):
TestContext.AddFormatter(obj =>
{
if (obj == null)
return x => "";
return x => JsonConvert.SerializeObject(x);
});

Unit Testing - How do I test this class

I have class Cache (wraps System.Runtime.Caching.MemoryCache) that I have created which has the following public methods:
bool Add(string key, object value)
bool Contains(string key)
How do I test the Contains() method without using the Add() method in the first place to add an item to the Cache??? Surely if I use the Add() method within the unit test for the Contains() method this would be wrong?
How do I test the Contains() method without using the Add() method in the first place to add an item to the Cache?
Assert that it returns false.
Surely if I use the Add() method within the unit test for the Contains() method this would be wrong?
Of course not. You're testing a unit which has a Contains() that differs in behaviour after you've called Add(). Not having tests for Contains() called after Add() would be wrong.
I think I understand your dilemma. You are asking if you use a new method to test another new method. Sort of testing an unknown with an unknown.
To me I would look at it as test isolation case of assumption. Let me explain...
The following applies if both methods are there and you are responsible for testing them.
In the first instance, you want to test the Add(,) method. In that case, I would 'assume' that all other methods work correctly. So in that case, I would run an Add(key,value) and check that it Asserts true, and then verify with a call to Contains(key) and ensure that it Asserts true. Even though Contains() is untested.
Then in the second instance, you assume that Add(,) is working properly and test the Contains() method. I always test based on the assumption that I've got blinkers on and testing something specific, a specific method, a specific class and run on the assumption that everything supporting required to run the test actually works.
In reality, this is not always the case and some of the supporting methods don't work as expected. But, the test will let you know. And that's what it's there for. To help reveal those issues.
You probably already have this test in mind but, here's a quick example where you can combine the testing of these two methods into a single test. Of course, you can split it into two tests (one thats Add() centric and one that's Contains() centric) but they will look fairly similar. I hope it helps.
public class SomeClass : MemoryCache
{
public SomeClass() : base("Test")
{
}
public bool Add(string key, object value)
{
return Add(key, value, DateTime.Now.AddDays(1));
}
}
[TestFixture]
public class TestSomeClass
{
[Test]
public void TestSomeClassMethod1()
{
var instance = new SomeClass();
const string key = "someKey";
Assert.IsFalse(instance.Contains(key));
Assert.IsTrue(instance.Add(key, new object()));
Assert.IsTrue(instance.Contains(key));
instance.Remove(key);
Assert.IsFalse(instance.Contains(key));
}
}
But in a pure TDD approach, you would do this:
Create the Add(,) method then write the following test:
[Test]
public void TestAdd()
{
var instance = new SomeClass();
const string key = "someKey";
Assert.IsTrue(instance.Add(key, new object()));
}
Then you would create the Contains() method and then write the following test:
[Test]
public void TestContains()
{
var instance = new SomeClass();
const string key = "someKey";
Assert.IsFalse(instance.Contains(key));
// A purest will say that you don't need the following Assert
// for the Add as it is not what you are testing.
// But I don't see any harm
Assert.IsTrue(instance.Add(key, new object()));
Assert.IsTrue(instance.Contains(key));
instance.Remove(key);
Assert.IsFalse(instance.Contains(key));
}

Overriding previously set function behavior of Typemock Isolator (WillThrow()/DoInstead())

Please check out this code:
public UserRepository GetUserRepositoryMock()
{
// mock all UserRepository instances.
var userRepositoryMock = Isolate.Fake.Instance<UserRepository>();
Isolate.Swap.AllInstances<UserRepository>().With(userRepositoryMock);
// make all public UserRepository members throw a NotSupportedException.
Isolate.WhenCalled(() => userRepositoryMock.Select(null)).WillThrow(new NotSupportedException());
Isolate.WhenCalled(() => userRepositoryMock.SelectOne(null)).WillThrow(new NotSupportedException());
Isolate.WhenCalled(() => userRepositoryMock.Save(null)).WillThrow(new NotSupportedException());
Isolate.WhenCalled(() => userRepositoryMock.Remove(null)).WillThrow(new NotSupportedException());
// ... et cetera until all public members of UserRepository will throw NotSupportedException.
}
[TestMethod]
public void ActivateUser_UserNotFound_ThrowsException()
{
var userRepositoryMock = GetUserRepositoryMock();
// override one of the public UserRepository members to return a specific value.
Isolate.WhenCalled(() => userRepositoryMock.SelectOne(null)).DoInstead(context =>
{
return null;
});
// call ActivateUser implementation.
RegistrationServices.ActivateUser("foo#bar.com", "password", "activation-code");
}
What this piece of code actually does is throw a NotSupportedException for all public members of UserRepository.
What I want this piece of code to do is make all public members of UserRepository throw a NotSupportedException except for the SelectOne() function, which returns null.
I want to make sure the ActivateUser() function of RegistrationServices does not call any function of the UserRepository other than the SelectOne() function I explicitly specified.
If it does, for example by changing the implementation of the ActivateUser() to make a call to Save() of UserRepository and not altering the corresponding *ActivateUser_UserNotFound_ThrowsException* test, I want the test to fail because the change might introduce unexpected behaviour. This way I can completely isolate my application from third parties and reduce coding errors to a minimum.
My questions regarding to this code and the principles behind it are:
How can I achieve the desired behaviour?
Are there any alternatives I can explore to achieve the desired behaviour?
Are the basic principles of the desired behaviour valid? i.e. Should I want to isolate the entire application from third parties for testing purposes, raise exceptions when unsuspected function is called and only return valid data when explicitly specified so?
Note: I work at Typemock
There are several approaches you can take here to test what you want.
For example, you can use the Isolate.Verify API to make sure no specific calls were made on your fake object.
This would allow you to not specify explicitly the return of other methods, as you can make sure that they did not occur:
[Test, Isolated]
public void ActivateUser_UserNotFound_ThrowsException()
{
var userRepositoryMock = Isolate.Fake.Instance<UserRepository>();
Isolate.Swap.AllInstances<UserRepository>().With(userRepositoryMock);
Isolate.WhenCalled(() => userRepositoryMock.SelectOne(null)).WillReturn(null);
// call ActivateUser implementation.
RegistrationServices.ActivateUser("foo#bar.com", "password", "activation-code");
Isolate.Verify.WasNotCalled(() => userRepositoryMock.Save(null));
Isolate.Verify.WasNotCalled(() => userRepositoryMock.Remove(null));
}
Isolator's WhenCalled() chains method behaviors in the order defined, meaning that in your original test, the first time SelectOne would throw an exception, the second time and on it would return null.
Hope that helps, if you have other questions please feel free to contact us via support, or here!
I'm not sure why you want to do things this way. You would be better setting up your mock object inside the test and creating a new mock object for each test.
this might seem like more work at first, but using the approach you have above will make your tests hard to follow and the GetUserRepositoryMock method less and less useful as you add more tests which want slightly different behaviour.
if what you want to do is just verify that those methods were not called then you can do this with the Isolate.Verify.WasNotCalled(x=>x.Select(null)); for each of the methods. I think this is a better approach that your setting up all methods to throw exceptions.
You could get something along the lines you want by having your GetUserRepositoryMock method take a lot of booleans which specify which methods to mock with the throw NotImplementedException, all defaulted to true. Then you could use named parameters to just specify the one you don't want to set. Something along these lines:
public UserRepository GetUserRepositoryMock(bool mockSelect=true, bool mockSelectOne=true, bool mockSave=true ... etc etc)
{
// mock all UserRepository instances.
var userRepositoryMock = Isolate.Fake.Instance<UserRepository>();
Isolate.Swap.AllInstances<UserRepository>().With(userRepositoryMock);
// make all public UserRepository members throw a NotSupportedException.
if(mockSelect)
Isolate.WhenCalled(() => userRepositoryMock.Select(null)).WillThrow(new NotSupportedException());
if (mockSelectOne)
Isolate.WhenCalled(() => userRepositoryMock.SelectOne(null)).WillThrow(new NotSupportedException());
if(mockSave)
Isolate.WhenCalled(() => userRepositoryMock.Save(null)).WillThrow(new NotSupportedException());
// ... et cetera until all public members of UserRepository will throw NotSupportedException where the corresponding flag is true.
}
then you could invoke it like this in your test where you don't want the SelectOne to be mocked:
[TestMethod]
public void ActivateUser_UserNotFound_ThrowsException()
{
var userRepositoryMock = GetUserRepositoryMock(mockSelectOne:false);
// override one of the public UserRepository members to return a specific value.
Isolate.WhenCalled(() => userRepositoryMock.SelectOne(null)).DoInstead(context =>
{
return null;
});
// call ActivateUser implementation.
RegistrationServices.ActivateUser("foo#bar.com", "password", "activation-code");
}
So you only have to specify the things which you want to be different from the default, using the named parameters.
I'm not saying I like this solution particularly, and there might well be a better solution using some of TypeMocks own methods, but this should give you what you want. You could tailor this method to actually do the Isolate.Verify.WasNotCalled() checks for each thing instead, based on the flags.

Categories