Can I reuse It.Any argument descriptors in Moq - c#

I have some code similar to
FooMock.Setup( m => m.Bar( It.Is<BarArg>( x => long_test_x_is_ok(x) ) );
naively, I thought I could rewrite this as:
var barArg = It.Is<BarArg>( x => long_test_x_is_ok(x) );
FooMock.Setup( m => m.Bar( barArg ) );
but Moq doesn't love me. Is there a may to do this?
Similarly, some of our class names are quite long. I'd like to refactor the calls to
It.IsAny<AnnoyinglyLongClassNameHere>()
into something shorter
var anyAlcnh = It.IsAny<AnnoyinglyLongClassNameHere>;
doesn't seem to work either.

The reason it does not work is Setup is actually taking in a Expression<Action<IFoo>> not just a Action<IFoo>.
It never actually calls the Action you passed in, what it does is it takes the expression, pulls it apart and parses each component piece. Because of that you can't pull out barArg because that would make barArg a "black box" to the expression parser and would not know what the variable represents.
The best you could do is
//Assuming Bar has the signature "void Bar(BarArg barArg)".
//If it was "Baz Bar(BarArg barArg)" use "Expression<Func<IFoo, Baz>>" instead.
Expression<Action<IFoo>> setup = m => m.Bar(It.Is<BarArg>(x => long_test_x_is_ok(x)));
FooMock.Setup(setup);
The IsAny has the same problem, however for that you could make an alias to shorten the class name.
//At the top of your file with your other using statements
using ShortName = Some.Namespace.AnnoyinglyLongClassNameHere;
//Down in your unit test
FooMock.Setup(m => m.Bar(It.IsAny<ShortName>());

Related

Handling lambda expression with generic property name

Working with EPiServer Find and trying to build a generic facet funcionality for it to simplify managing which facet should be enabled. I would like to construct two generic methods, one for adding active filters to perform the hits search and one to perform the available facet filters remaining.
The first method will perform the following (specific code for brand filter):
var brandFilter = client.BuildFilter<FashionProduct>();
foreach (var facet in SelectedGroup.Facets.Where(x => x.Selected))
{
brandFilter = brandFilter.Or(x => x.Brand.Match(facet.Key));
}
query = query.Filter(brandFilter);
I would like to be able to call it in a generic way so I could base the available facets on some simple list of strings or objects. Like this:
query = AddFilterFacet<FashionProduct>(query, "Brand", SelectedGroup.Facets)
So the method would take the type of object to filter on, the query to append the filters on, the name of the property to filter on and the list of values to add.
The second method is similar but relates more to perform the following:
facetQuery = facetQuery.TermsFacetFor(x => x.Brand)
...
var brandFacets = facetResult.TermsFacetFor(x => x.Brand).Terms;
Is it possible to build this kind of functionality? The biggest questionmark I have is how to translate the "Brand" input string to be the Brand Property in x => x.Brand
private void AddFilterFacet<T>(IClient client, ref ITypeSearch<T> query, string propertyName, List<FacetOption> facets)
{
var filter = client.BuildFilter<T>();
foreach (var facet in facets)
{
filter = filter.Or(x => x.????.Match(facet.Key));
}
query = query.Filter(filter);
}
The .Or method takes a
System.Linq.Expressions.Expression<Func<T, Find.Api.Querying.Filter>>
so perhaps something can be used to make a proper generic call to it
It's definitely possible to create generic lambda expressions, it's just not easy and requires a lot of reflection code.
I haven't done it in a while, but maybe if you look at the code i created for something similar a while ago (Generic lambda expressions) it'll help. I'm sure someone with fresher experience will help you out here soon enough.
Decimal precision attribute <-- take a look a this answer witch has code to genereate modelBuilder.Entity<CLASS>().Property(OBJECT=> OBJECT.PROPERTY).HasPrecision(12, 10) automatically from an attribute in a class

Using moq to verify a call to a function with param parameters

I have an ILogger interface with LogTrace(string value, params object[] parameters). Now I want to verify that the LogTrace is called and the string to log contains some id. The problem is that it can be called differently. E.g.
1) LogTrace("MyString " + id)
2) LogTrace("MyString {0}", id)
and so on.
Is there a good way with Moq to verify all the scenarios? I can only think of creating a hand-made mock that will format the string that will be available for verification.
mock.Verify( m => m.LogTrace( It.IsAny<string>(), It.IsAny<object[]>() ) );
The params object[] is passed to the method as object[] anyway so you just have to match the array somehow (as above for example, this accepts anything).
If you need more control over the list, use the It.Is matcher which allows you to create your own predicate:
mock.Verify( m => m.LogTrace( It.IsAny<string>(),
It.Is<object[]>(ps =>
ps != null &&
ps.Length == 1 &&
ps[0] is int &&
(int)ps[0] == 5
) ) );
This example shows how to verify if the param list is not empty and contains 5 as the only parameter of type int.
I don't think there is an easy way for doing what you need here. The problem is that you need to ensure that a certain combination of values will be passed to your method, which results in many different verifiable scenarios:
String contains ID AND parameters contains ID - pass
String contains
ID AND parameters does not contain ID - pass
String does not contain
ID AND parameters contains ID = pass
String does not contain ID AND
parameters does not contain ID - fail
However, Moq does not support this sort of conditional expressions between different arguments of your verifiable method. One possible solution is to check for the absence of an id, instead of its presence in either argument. Try something like:
mock.Verify(m => m.LogTrace(
It.Is<string>(s => !s.Contains(id)),
It.Is<object[]>(o => !o.Contains(id))), Times.Never());
What we are doing here is verifying whether the fail condition is ever met - that is, your string does not contain an id, and neither does your object array. We use Times.Never() to make sure that this situation should never happen.
Keep in mind, however, that the code might not be obvious at first glance; make sure you properly explain your intent once you write it.
You could try to use the Callback, but it get fairly convoluted (not tested):
var mock = new Mock<ILogger>();
string trace = null;
mock.Setup(l => l.LogTrace(It.IsAny<string>(), It.IsAny<object[]>()))
.Callback((s1, par) =>
{
trace = string.Format(s1, par);
});
//rest of the test
Assert.AreEqual(expected, trace);
If ILogger has a small interface, you might consider implementing a stub manually (that would keep all the lines it is supposed to log), and verify that at the end of the test. If you have multiple lines being logged than this will be a more readable setup.

How to test for a Match with FakeItEasy on a predicate call?

I have the following call in my code:
var dbResults = new List<CrossReferenceRelationshipEF>();
dbResults = dateTimeFilter == null
? new List<CrossReferenceRelationshipEF>(
CrossReferenceRelationshipRepository.GetAll()
.ToList().OrderBy(crr => crr.ToPartner))
: new List<CrossReferenceRelationshipEF>(
CrossReferenceRelationshipRepository.SearchFor(
crr => crr.HistoricEntries
.Any(he => he.ModifiedDatetime > dateTimeFilter))
.ToList().OrderBy(crr => crr.ToPartner));
and I am trying to use FakeItEasy to verify that when the dateTimeFilter has a value, the SearchFor(…) is being called within my repository with the correct Function.
So my test looks something like this:
A.CallTo(() => crossReferenceRelationshipRepositoryMock.SearchFor(A<Expression<Func<CrossReferenceRelationshipEF,bool>>>.That
.Matches(exp => Expression.Lambda<Func<DateTime>>(((BinaryExpression)exp.Body).Right).Compile().Invoke() == filterByDate)))
.MustHaveHappened(Repeated.Exactly.Once);
Which is not correct.
What would be a way to test the whether or not I am calling SearchFor(…) with the correct expression?
crr => crr.HistoricEntries.Any(he => he.ModifiedDatetime > dateTimeFilter)
The actual value being passed into SearchFor(…) is DateTime.MinValue so I changed my assertion to:
A.CallTo(() => crossReferenceRelationshipRepositoryMock.SearchFor(A<Expression<Func<CrossReferenceRelationshipEF, bool>>>.That
.Matches(exp => Expression.Lambda<Func<DateTime>>(((BinaryExpression)exp.Body).Right).Compile().Invoke() == DateTime.MinValue)))
.MustHaveHappened(Repeated.Exactly.Once);
which is failing and the exception I am getting is
System.InvalidCastException:
Unable to cast object of type 'System.Linq.Expressions.MethodCallExpressionN'
to type 'System.Linq.Expressions.BinaryExpression'.
and I am not sure what I am doing wrong...
Disclosure - VasilisP and I chatted a little about this yesterday.
In a way, this isn't really a FakeItEasy problem. Your approach for setting up an argument matcher within an A.CallTo call is sound. The problem is that the lambda you supplied to match the predicate is not working. This brings the question down to the "how can I tell if an expression is what I want it to be?".
There are other StackOverflow questions that ask questions similar to this, such as
Most efficient way to test equality of lambda expressions,
How to check if two Expression<Func<T, bool>> are the same, and
How to test expressions equality
One of those approaches may work for you.
However, the immediate cause of the exception you see is that the passed-in predicate isn't a BinaryExpression, it's a MethodCallExpression. You could consider altering your test to account for that and follow the path where it leads you.
I filled in some class definitions and extracted the matcher to this function and was able to at least locate the dateArgument in the predicate:
public bool IsPredicateGood(Expression<Func<CrossReferenceRelationshipEF, bool>> predicate)
{
var typedPredicate = (MethodCallExpression) predicate.Body;
var innerPredicate = ((LambdaExpression)typedPredicate.Arguments[1]).Body;
var dateArgument = ((BinaryExpression) innerPredicate).Right;
return dateArgument != null; // not a real test yet, but you could adapt
}
In general, though, I'd warn against testing quite like this - it seems a little fragile to me. Of course, you may have a good reason for this approach. But if it suits you, another way to go may be to just capture the predicate and then interrogate it by having it run against a known list of candidate objects. If it filters the way you want, then it passes.
That way if someone changes the passed-in predicate in a way that would still work, perhaps by switching the operator to a < with the date on the left, the test would still work. I just throw that out as another option.
Sorry I should have answered this earlier. It is true that Blair Conrad and I had a chat and he helped me understand how to test the predicates better. Based on his recommendation I came up with the following solution.
In my tests I created a helper Expression extractor show below:
private static string ExpressionExtractor(Expression<Func<CrossReferenceRelationshipEF, bool>> predicate)
{
var expression = ((BinaryExpression) ((LambdaExpression) ((MethodCallExpression) predicate.Body).Arguments[1]).Body);
var value = Expression.Lambda<Func<object>>(Expression.Convert(expression.Right, typeof (object))).Compile().Invoke();
return value.ToString();
}
And then in my tests I could do my assert like this:
//Assert
A.CallTo(() => crossReferenceRelationshipRepositoryMock.SearchFor(A<Expression<Func<CrossReferenceRelationshipEF, bool>>>.That
.Matches(exp => ExpressionExtractor(exp) == "20/01/2014 14:06:55")))
.MustHaveHappened(Repeated.Exactly.Twice);

Func<> or method in test code?

I saw this loop in test code:
foreach ( StuffId Id in Result.GetIdList() )
{
if ( Id.Level == 3 )
{
Level3Id = Id.ToString();
}
if ( Id.Level == 5 )
{
Level5Id = Id.ToString();
}
}
Other tests imply that either there is only one Id for each level or when there are multiples for each level then the Id will be the same.
Being slightly obsessed with LINQ right now, I first refactored to this:
IEnumerable<StuffId> Ids = Result.GetIdList();
Level3Id = Ids.Where( x => x.Level == 3 ).First().Id.ToString();
Level5Id = Ids.Where( x => x.Level == 5 ).First().Id.ToString();
Then the code repetition bothered me so I refactored to this:
IEnumerable<StuffId> Ids = Result.GetIdList();
Func<int,string> IdFromLevel =
level => Ids.Where( x => x.Level == level ).First().Id.ToString();
Level3Id = IdFromLevel(3);
Level5Id = IdFromLevel(5);
A colleague wondered why I didn't use a method in place of the delegate. My reasoning is a method would be slightly more 'messy' because I'd have to additionally pass in the collection and that using a delegate is no big deal for a simple test (for which terse, readable and no branching are good qualities).
I had a look on SO, of course, and found this seemingly relevant question:
C#: Func<> instead of methods?
where the consensus seems to favour a method over a delegate. Does the same apply in my case?
It is a question of reuse. If you are using methods that might be reusable in other cases, you should define them seperately.
But if you have only short statements that additionally vary, you should stick with anonymous functions/lambda-expressions, these might result in a better runtime-behavior.
From SO:
There is no advantage in the code you posted. In your code, using the delegate just adds complexity as well as an extra runtime cost - so you're better off just calling the method directly.
However, delegates have many uses. "Passing around" to other methods is the primary usage, though storing a function and using it later is also very useful.
LINQ is built on top of this concept entirely. When you do:
var results = myCollection.Where(item => item == "Foo");
You're passing a delegate (defined as a lambda: item => item == "Foo") to the Where function in the LINQ libraries. This is what makes it work properly.
Not sure about pros and cons, but reading these articles might help you to take a better decision:
http://msdn.microsoft.com/en-in/library/bb549151.aspx
http://msdn.microsoft.com/en-us/library/orm-9780596516109-03-09.aspx
http://msdn.microsoft.com/en-in/library/98dc08ac.aspx
I would go with the first block:
foreach (StuffId Id in Result.GetIdList())
{
if (Id.Level == 3)
{
Level3Id = Id.ToString();
}
if (Id.Level == 5)
{
Level5Id = Id.ToString();
}
}
This does loop the collection only once. I see you don't worry about performance here, but for me its not a matter of performance or optimization. It's a matter of doing something logically correct way. Why do something twice if it could be in one step (provided readability is not hurt).
The added benefit is that you don't have the dilemma between Func<,> and method, and the related complexities. As far as number of characters or ease of typing goes, its almost the same, except you're writing it horizontally (in the second case) than vertically. You can even write the above in two lines inside the foreach block.
If you're bent on writing the two actions separately, I would make the choice based on whether the function has relevance outside the scope of current method in this case. It seems to me that its a trivial predicate which is relevant only for the two assignments. So I like:
var Ids = Result.GetIdList();
Func<int, string> IdFromLevel = level => Ids.Single(x => x.Level == level).Id.ToString();
Level3Id = IdFromLevel(3);
Level5Id = IdFromLevel(5);
Prefer Single here over First..

Unit test delegate action is called

I have a Dictionary that I am using to avoid writing big if statements. It maps an enum to an action. It looks like this:
var decisionMapper = new Dictionary<int, Action>
{
{
(int) ReviewStepType.StandardLetter,
() =>
caseDecisionService.ProcessSendStandardLetter(aCase)
},
{
(int) ReviewStepType.LetterWithComment,
() =>
caseDecisionService.ProcessSendStandardLetter(aCase)
},
{
(int) ReviewStepType.BespokeLetter,
() =>
caseDecisionService.ProcessSendBespokeLetter(aCase)
},
{
(int) ReviewStepType.AssignToCaseManager,
() =>
caseDecisionService.ProcessContinueAsCase(aCase)
},
};
then I call it like this in my method:
decisionMapper[(int) reviewDecisionRequest.ReviewStepType]();
My question is how can I unit test these mappings?
(I am using Nunit and c# 4.0)
How can I assert that when I call my decisionMapper - that 1 is equal to the call -caseDecisionService.ProcessSendStandardLetter(aCase).
Thanks very much.
You can't compare anonymous delegates (see this link). You have to use a little bit of reflection to check the Method property of the Action delegate. It has to match the MethodInfo of the caseDecisionService method that should be invoked. For example (You may rewrite to use a function to make code shorter):
MethodInfo methodToCall =
decisionMapper[(int)ReviewStepType.StandardLetter].Method;
MethodInfo expectedMethod =
typeof(CaseDecisionService).GetType().GetMethod("ProcessSendStandardLetter");
Assert.AreSame(expectedMethod, methodToCall);
I personally wouldn't bother writing a unit test which directly checks which action is invoked in each case.
Assuming this dictionary is part of a larger system, I'd write one test which goes through each of the Dictionary actions via whatever class contains the Dictionary. I want to check my code gives me outcomes I expect (the outcome of calling ProcessSendStandardLetter() or ProcessSendBespokeLetter(), for example); I'm less interested in checking exactly how it does it.
Thanks everyone for helping with this. This was what I did in the end.
I mocked the Action Service call, then invoked the dictionary's value, then called AssertWasCalled / AssertWasNotCalled. Like this:
mapper[(int) ReviewStepType.StandardLetter].Invoke();
caseDecisionService.AssertWasCalled(c => c.ProcessSendStandardLetter(aCase),
options => options.IgnoreArguments());
caseDecisionService.AssertWasNotCalled(c =>
c.ProcessSendBespokeLetter(aCase),
options => options.IgnoreArguments());
caseDecisionService.AssertWasNotCalled(c =>
c.ProcessContinueAsCase(aCase),
options => options.IgnoreArguments());

Categories