Moq It.Is<> not matching - c#

This code:
hub.MockedUserRepository.Setup(r => r.Update(It.IsAny<ControllUser>()))
.Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
.Verifiable();
Will print
NULL = True
So i am thinking using this matching will catch it:
var zombieDisconnectParameterMatcher = It.Is<ControllUser>(x => x.Zombies[0].ConnectionId == null);
hub.MockedUserRepository.Setup(r => r.Update(zombieDisconnectParameterMatcher))
.Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
.Verifiable();
But it does not.
Why?

By looking at the source code of It, it has to do with expression trees. I like the question; they can be quite puzzling. If you would take a look at the following method definitions:
public static TValue It.Is<TValue>(Expression<Func<TValue, bool>> match)
{
return Match<TValue>.Create(
value => match.Compile().Invoke(value),
() => It.Is<TValue>(match));
}
public static T Match.Create<T>(Predicate<T> condition, Expression<Func<T>> renderExpression)
{
// ...
return default(T);
}
If you would execute the following line:
var zombieDisconnectParameterMatcher = It.Is<ControllUser>(x => x.Zombies[0].ConnectionId == null);
Then It.Is<ControllUser>() will try to call a method called Match.Create<ControllUser>(), which returns the default of ControllUser. I assume ControllUser is a class and therefore zombieDisconnectParameterMatcher will be null. You should be able to see this with the debugger. So what actually you're calling is:
hub.MockedUserRepository.Setup(r => r.Update(null))
.Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
.Verifiable();
When executing the Update method with a non-null ControllUser (from the method that is being tested for example), the callback will not trigger. It simply doesn't match the criteria since it's not null. You would see the verification fail, also.
To resolve this issue, either inline the zombieDisconnectParameterMatcher variable, or make it an expression typed variable (eg. Expression<Func<...>>). The latter will make sure that the code is not executed, but treated as an expression which the mock framework can reason about ('is Update being called with Zombies[0].ConnectionId == null?').

It depends how the ControllUser instance is instantiated. If the instance that you refer to within the mock is not the actual instance referred to in the code under test, the Setup will fail. You will need to ensure that the instance of ControllUser referred to in the code under test is the same object as the one in the test code. If it isn't, you'll have to test for it using It.IsAny<ControllUser>() and a callback, as your first example shows. It's hard to say with certainty without seeing more of the code that you're testing.

Related

Mock method return based on object parameter

I have the following (simplified) code:
public string methodName(ClassType object)
{
If(object.value == 1)
return "Yes";
else If(object.value == 2)
return "No";
else
return "whatever";
}
I am then calling this method in a unit test, and need to mock the return type based on the object value:
_Service.Setup(x => x.methodName(new methodName { value = 1}).Returns("Yes");
_Service.Setup(x => x.methodName(new methodName { value = 2}).Returns("No");
I know what I have written is wrong - but how can I achieve this?
You're on the right track. With Moq, you need to specify exactly which setup should match each input. You do it like this:
_Service.Setup(x => x.methodName(It.IsAny<ClassType>())).Returns("whatever");
_Service.Setup(x => x.methodName(It.Is<ClassType>(o => o.value == 1))).Returns("Yes");
_Service.Setup(x => x.methodName(It.Is<ClassType>(o => o.value == 2))).Returns("No");
The first line there sets up the mock to return "whatever" whenever this method is called with any value. The following two lines override that behavior for specific values.
I'd check out Moq's Quickstart guide for more details, and the Matching Arguments section in particular.
I´m not that familiar with Moq, however I asume the following should do it. You should provide a single Returns for every possible value for your parameter:
_Service.Setup(x => x.methodName(It.Is<ClassType>(y => y.value == 1))).Returns("Yes");
_Service.Setup(x => x.methodName(It.Is<ClassType>(y => y.value == 2))).Returns("No");
This way whenever your methodName-method is called with object.value == 1, "Yes" is returned, while object.value == 2 resolves to the method returning "No".
However to me this makes not much sense as you´re mocking the behaviour of methodName with the exact same behaviour. I suppose this is just for research.

Issue with LINQ 'OR' condition when adding .ToList (or ToArray) in the end

Working with DB through DataContext.
Have such operation:
var flat = StavRealtyDb.TargetFlat
.Where(x => true || _some condition_).ToList();
So, if the FIRST part of condition is true, the SECOND part should be skipped by compiler, right?
But it doesn't happens. The same problem will happen, if there would be .ToArray().
BUT, if it won't be anything like .ToList or .ToArray in the end - compiler will SKIP the second part of condition.
What is the problem? Is it normal? :)
UPDATE
Ok, thanks for your answers! I understood that it's normal. But the problem is that the 1st part of the condition contains: someobject == null; the second part contains: someobject.Contains().
.Where(x => someobject == null || someobject.Field.Contains(x.somefield))
So I have ArgumentNullException when someobject == null (my hope was that the 1st part will return true and the 2nd part WILL NOT execute). Could you advise me, how can I solve this problem?
P.S: actually, the .Where() expression is more complex:
.Where(x=> (part1 || part 2) && (part1 || part2) && ......)
You're doing Where on IQueryable and the argument is an Expression not a Func
http://msdn.microsoft.com/en-us/library/vstudio/bb535040%28v=vs.100%29.aspx
The Expression is just passed to the underlying Where implementation.
I found the subject interesting so I've created an example. Suppose we have following code:
using System;
using System.Linq.Expressions;
namespace TestApplication
{
class CompilerTest
{
public void Test()
{
Func<bool> func = () => true || Foo();
Expression<Func<bool>> expr = () => true || Foo();
}
public static bool Foo()
{
return new Random().Next() % 2 == 0;
}
}
}
We build it (Release build) and the decompiled code looks like this:
using System;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace TestApplication
{
internal class CompilerTest
{
[CompilerGenerated]
private static Func<bool> CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1;
public CompilerTest()
{
base.\u002Ector();
}
public void Test()
{
if (CompilerTest.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1 == null)
{
// ISSUE: method pointer
CompilerTest.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1 = new Func<bool>((object) null, __methodptr(\u003CTest\u003Eb__0));
}
Func<bool> func = CompilerTest.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1;
(Expression<Func<bool>>) (() => true || CompilerTest.Foo());
}
public static bool Foo()
{
return new Random().Next() % 2 == 0;
}
[CompilerGenerated]
private static bool \u003CTest\u003Eb__0()
{
return true;
}
}
}
and if we hide compiler generated code (dotPeek option) it looks like this:
using System;
using System.Linq.Expressions;
namespace TestApplication
{
internal class CompilerTest
{
public void Test()
{
Func<bool> func = (Func<bool>) (() => true);
(Expression<Func<bool>>) (() => true || CompilerTest.Foo());
}
public static bool Foo()
{
return new Random().Next() % 2 == 0;
}
}
}
As we can see the Func code specified in lambda was optimized (that was the real question if the compiler optimizes that). The code specified in expression was obviously not optimized (since it's an Expression so there is nothing to optimize at this point from the compiler perspective).
The answers so far touch some issues that play a role but don't cover the whole picture. Also, it is essential information that the second condition is a Contains statement. So let's say the core statement is
StavRealtyDb.TargetFlat.Where(x => true || someList.Contains(x.Id))
As said, the whole LINQ statement is an Expression, so the compiler doesn't apply any optimizations. So if all is well -
the .Net runtime succeeds in creating an expression,
passes it to the EF query provider,
the query provider translates it into SQL,
ADO.Net runs the SQL,
the database executes it, and returns a result set back to the .Net runtime,
the .Net runtime creates objects from the result set and returns them into var flat.
In this course of events, the second predicate is always read by the .Net runtime, irrespective of how many predicates precede it, but evaluated by the database if the query optimizer finds reasons to do so.
Now something's wrong: someList is null. Now the whole process comes to a halt at step 3. The query provider tries to read someList (in order to convert it to an IN clause). But, of course, that fails with a null reference.
So you have to make sure that someList is never null (it could be an empty list) or you could compose the Where condition: only if someList isn't null, you include the Contains predicate.
I think this is normal and by-design for Linq Providers. In this case the Linq Provider is designed to take the Where expression and turn it into Sql and execute it on the Sql Server.
Where() will return an IQueryable<>, which you can see as a query ready to be executed. It is, however, only built in the Where() and it will be executed whenever the actual data is needed - in this case, when calling ToList(). The query will hold the OR and thus it is completely normal behaviour that it is not short circuited because it is simply not executed within the Where().
If you'd like to understand it better, try splitting it up and put a breakpoint at the Where().
var query = StavRealtyDb.TargetFlat.Where(x => true || _some condition_);
var actualData = query.ToList();
When hovering over query while debugging, you will notice it being an actual query like
SELECT `Extent1`....
And after calling ToList(), you will notice that the data is retrieved from the database and put in a List.

ArgumentNullException unhandled

I'm new to C#. I have an implicit typed variable defined like this:
var item = doc.DocumentNode.SelectNodes("//body[#id='person']")
.Select(p => p.InnerText);
This var sometimes returns null. And that's where visual studio asks me to handle the ArgumentNullException. But if I do that my var remains unknown to the rest of my try-catch and I can no longer use it.
Someone advised me to use the null object design pattern but I don't how am I supposed to implement it for a var. Does anyone know how I should handle such situations because I'm tired of handling the null case each and every time.
I am assuming, as it seems, that the problem is SelectNodes returning null when no results are found. This is a pattern I come across frequently: a sequence of operations, several of which can return null values, where the production of any null should cause the entire sequence to produce null.
One solution is to use what functional programmers would call the Maybe monad's Bind method:
public static U IfNotNull<T, U>(this T self, Func<T, U> func)
where U : class
{
return (self != null) ? func(self) : null;
}
This will "propagate" nulls rather than throwing exceptions. Then,
doc.DocumentNode
.SelectNodes("//body[#id='person']")
.IfNotNull(nodes => nodes.Select(p => p.InnerText));
If SelectNodes returned IEnumerable<XmlNode>, you could use Enumerable.Empty<>:
(doc.DocumentNode.SelectNodes("//body[#id='person']") ?? Enumerable.Empty<XmlNode>())
.Select(p => p.InnerText);
Or, for better readability, write an extension method to avoid worrying about operator syntax:
public static T Coalesce<T>(this T self, T other)
where T : class
{
return self ?? other;
}
And:
doc.DocumentNode.SelectNodes("//body[#id='person']")
.Coalesce(Enumerable.Empty<XmlNode>())
.Select(p => p.InnerText);
These are all various ways of deferring null checks until you're ready to deal with the results, without having to catch NullPointerExceptions (or ArgumentExceptions in the case of extension methods). Note that any of these that produce null values could produce default values instead if you tossed a simple ?? operator at the end.
IEnymerable<HtmlNode> v = null;
var item = doc.DocumentNode.SelectNodes("//body[#id='person']");
if (item != null)
{
v = item.Select(p => p.InnerText);
}

Verifying many properties cleanly [separately outside of single verify call] of an argument passed to Mock?

saveThemeAS.Verify(service => service.Execute(FakeUserID, It.Is<LayoutENT.Theme>(savedTheme =>
savedTheme != null
&& savedTheme.Name == FakeCopiedThemeName
&& savedTheme.ThemeID == 0
&& savedTheme.WidgetSkins.Any(skin => skin.Name == FakeWidgetSkinName && skin.WidgetSkinID == 0)
&& savedTheme.SiteStyles.Any(style => style.SiteStyleID == FakeStyleID && style.SiteStyleID == 0)
)));
Expected invocation on the mock at least once, but was never performed:
The basic problem here is I just get a failure, but I don't know specifically what failed/ what was not set appropriately as it could be any one of the 5 conditions above.
I would like to check each condition above seperately. Is there a slick way to do this with Moq without creating multiple tests? I thought it would be nice to be able to capture the argument passed to the mock and then test against that, but I haven't been able to find an elegant way to do so.
In essence, what you are asking for is for your inner lambda to perform a series of assertions rather than simply evaluate to a boolean value.
So let's do exactly that :)
saveThemeAS.Verify(service => service.Execute(FakeUserID, It.Is<LayoutENT.Theme>(savedTheme =>
{
Assert.IsNotNull(savedTheme);
Assert.AreEqual(FakeCopiedThemeName, savedTheme.Name);
Assert.AreEqual(0, savedTheme.ThemeID)
etc...
return true;
}
)));
You could move the assertions to a separate method for clearity.
If you want to get rid of the "return true;" you could write a wrapper for Action<T> that returns a Func<T,bool> that always returns true. That way you could write something along the lines of:
saveThemeAS.Verify(service => service.Execute(FakeUserID, It.Is<LayoutENT.Theme>(ReturnsTrue(CheckTheme))))
I think my approach to this problem would be to use a callback in the mock setup, such that the callback saves a copy of the savedTheme object that was passed to it. Then I'd perform asserts later in my unit test. This preserves the triple-A (Arrange, Act, Assert) pattern and seems cleaner than putting the assert logic into the mock setup. So for example:
protected static LayoutENT.Theme savedTheme;
// Arrange
themeParam = null;
saveThemeAS.Setup(service => service.Execute(FakeUserID, It.Is<LayoutENT.Theme>)
.Callback<layoutENT.Theme>(p => savedTheme = p);
// Act
// Calls the subject under test
// Assert
Assert.IsNotNull(savedTheme);
Assert.AreEqual(FakeCopiedThemeName, savedTheme.Name);
Assert.AreEqual(0, savedTheme.ThemeID)
etc...

Multiple Moq It.Is<string>() Matching Arguments

With Moq, is it valid to have more than one Matching Argument?
It.Is<string>()
In this example I want the mockMembershipService to return a different ProviderUserKey depending on the User supplied.
mockMembershipService.Setup(
x => x.GetUser(
It.Is<string>(
s => s.Contains("Joe")))
.ProviderUserKey)
.Returns("1234abcd");
mockMembershipService.Setup(
x => x.GetUser(
It.Is<string>(
s => s.Contains("Tracy")))
.ProviderUserKey)
.Returns("5678efgh");
The SetUp defaults to the second statement rather than evaluating each on its own merits.
Isn't it confusing? You are trying to mock GetUser method but you set the Returns for that function's return value's property. You also want to state return type's property based on mocked method.
Here's a way a more clear way:
mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>())
.Returns<string>(GetMembershipUser);
Here's a method to create the membership mock:
private MembershipUser GetMembershipUser(string s)
{
Mock<MembershipUser> user =new Mock<MembershipUser>();
user.Setup(item => item.ProviderUserKey).Returns(GetProperty(s));
return user.Object;
}
Then you write a method for setting that property:
private string GetProperty(string s)
{
if(s.Contains("Joe"))
return "1234abcd";
else if(s.Contains("Tracy"))
return "5678efgh";
}
If you want to restrict input to just "Joe" and "Tracy", you can specify multiple conditions in It.Is<T>(). Something like
mockMembershipService.Setup(x => x.GetUser(It.Is<String>(s => s.Contains("Joe")
|| s.Contains("Tracy")))
.Returns<string>(/* Either Bartosz's or Ufuk's answer */);
Succesive Setup calls nullify previous setups.
You could use your argument in your return callback:
mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>()).ProviderUserKey).Returns<string>(s =>
{
if(s.Contains("Joe"))
return "1234abcd";
else if(s.Contains("Tracy"))
return "5678efgh";
});
If it's important to you to assert the argument passed, you also need It.Is<string>(...) instead of It.IsAny<string>(...).
Please check Introduction to Moq > Matching Arguments documentation:
// matching Func<int>, lazy evaluated
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true);
// matching ranges
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true);
// matching regex
mock.Setup(x => x.DoSomething(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo");

Categories