Verify parameter of parameter class in moq setup - c#

context.Setup(x => x.ExecuteQuery(It.IsAny<GetBrowserByNameQuery>())).Returns(value: null);
Query class:
public class GetApplicationByNameQuery : IQuery<Application, Application?>
{
private readonly string _name;
public GetApplicationByNameQuery(string name)
{
_name = name;
}
public Application? Execute(IQueryable<Application> queryable)
{
return queryable.SingleOrDefault(x => x.Name == _name);
}
}
GetBrowserByNameQuery requires a string, I do not succeed to test the string passed to GetBrowserByNameQuery.
Following example does not work because it's an other instance of GetBrowserByNameQuery
context.Setup(x => x.ExecuteQuery(new GetBrowserByNameQuery>(command.Name))).Returns(value: null);

You could try following approach:
GetBrowserbyNameQuery resultQuery = null;
context
.Setup(x => x.ExecuteQuery(It.IsAny<GetBrowserByNameQuery>()))
.Returns(value: null)
.Callback<GetBrowserByNameQuery>(query => { resultQuery = query; });
Now in resultQuery you have an actual instance of class, which was used as argument. And you can assert (if class has some public property for Name) with assertion library you use. For example for FluentAssertions:
resultQuery.Name.Should().Be(command.Name)
If GetBrowserByNameQuery doesn't expose Name, there is no easy way to check it. Constructor could not be mocked, so only options you have:
access private field via reflections, which is super ugly and breaks unit testing principles
wrap creation of a GetBrowserByNameQuery with factory, and then mock the factory and check if factory method was called with a correct argument

Related

Test that property has child validator FluentValidation

The below test fails when I run it. I have an object, instruction that has a number of properties, most of which require their own validators. I want to be able to check that the validators for these child properties are present when set by the parent validator.
[Test]
public void ChildValidatorsSet()
{
_validator.ShouldHaveChildValidator(i => i.Property, typeof(FluentPropertyValidator));
_validator.ShouldHaveChildValidator(i => i.AdditionalInformation, typeof(FluentAdditionalInformationValidator));
}
Within the validator for this class I have the below rules defined that ensure the property in quest has a value set and sets a validator when the property is not null.
public FluentRemortgageInstructionValidator()
{
RuleFor(si => si.Property)
.NotNull().WithMessage("Solicitor Instruction: Instructions must have a linked property.");
RuleFor(si => si.Property)
.SetValidator(new FluentPropertyValidator()).When(si => si.Property != null);
RuleFor(si => si.AdditionalInformation)
.NotNull().WithMessage("Remortgage instructions must have an additional information table.");
RuleFor(si => si.AdditionalInformation)
.SetValidator(new FluentAdditionalInformationValidator()).When(si => si.AdditionalInformation != null);
}
Instruction class:
public class Instruction
{
[Key]
public AdditionalInformation AdditionalInformation { get; set; }
public Property Property { get; set; }
}
}
When an Instruction object with a valid Property property is passed through to the validator the validator should then set validators for Property and AdditionalInformation. Which is what happens when I run my code.
However I am unable to test for this, as there is no way to pass a valid object through to the ShouldHaveChildValidator method, and therefore no child validator is being set.
How do I design a test to check that these child validators are being set properly?
I'll give you an option so you can achieve what you want here, however I have to say that I haven't thought thoroughly about any side effects, so bear that in mind.
Your validators will always be set regardless of the property values, that's why you don't have to pass an instance of any object when calling ShouldHaveChildValidator method. The fact that they get executed or not is another story, and that as you know will depend on your rulesets.
So I cloned the fluent validation git repo and checked out how does the code check for the existence of the child validators.
For this call:
_validator.ShouldHaveChildValidator(i=>i.Property, typeof(FluentPropertyValidator));
This is what is does:
It gets the matching validators for the property expression you pass
in to the method call: i => i.Property
It filters the matching validators to get only those of type IChildValidatorAdaptor.
It throws an error if none of the selected validators are assignable from the type you pass to the method call: FluentPropertyValidator
It seems the code is missing the case where the validator is wrapped by another validator. That's the case of DelegatingValidator class which, by the way, is the type your child validator uses. So one possible solution is to also take those validator types into consideration.
I created a extension method you can use following the same pattern of the original one. Due to my lack of creativity when naming things (naming is tough), I named ShouldHaveChildValidatorCustom. This method is the same method in the code that also calls a couple of another methods that I just copied over from the sources of the FluentValidation so I could add the small modification.
Here is the complete extension class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using FluentValidation.Internal;
using FluentValidation.TestHelper;
using FluentValidation.Validators;
namespace YourTestExtensionsNamespace
{
public static class CustomValidationExtensions
{
public static void ShouldHaveChildValidatorCustom<T, TProperty>(this IValidator<T> validator, Expression<Func<T, TProperty>> expression, Type childValidatorType)
{
var descriptor = validator.CreateDescriptor();
var expressionMemberName = expression.GetMember()?.Name;
if (expressionMemberName == null && !expression.IsParameterExpression())
throw new NotSupportedException("ShouldHaveChildValidator can only be used for simple property expressions. It cannot be used for model-level rules or rules that contain anything other than a property reference.");
var matchingValidators = expression.IsParameterExpression() ? GetModelLevelValidators(descriptor) : descriptor.GetValidatorsForMember(expressionMemberName).ToArray();
matchingValidators = matchingValidators.Concat(GetDependentRules(expressionMemberName, expression, descriptor)).ToArray();
var childValidatorTypes = matchingValidators
.OfType<IChildValidatorAdaptor>()
.Select(x => x.ValidatorType);
//get also the validator types for the child IDelegatingValidators
var delegatingValidatorTypes = matchingValidators
.OfType<IDelegatingValidator>()
.Where(x => x.InnerValidator is IChildValidatorAdaptor)
.Select(x => (IChildValidatorAdaptor)x.InnerValidator)
.Select(x => x.ValidatorType);
childValidatorTypes = childValidatorTypes.Concat(delegatingValidatorTypes);
var validatorTypes = childValidatorTypes as Type[] ?? childValidatorTypes.ToArray();
if (validatorTypes.All(x => !childValidatorType.GetTypeInfo().IsAssignableFrom(x.GetTypeInfo())))
{
var childValidatorNames = validatorTypes.Any() ? string.Join(", ", validatorTypes.Select(x => x.Name)) : "none";
throw new ValidationTestException(string.Format("Expected property '{0}' to have a child validator of type '{1}.'. Instead found '{2}'", expressionMemberName, childValidatorType.Name, childValidatorNames));
}
}
private static IPropertyValidator[] GetModelLevelValidators(IValidatorDescriptor descriptor)
{
var rules = descriptor.GetRulesForMember(null).OfType<PropertyRule>();
return rules.Where(x => x.Expression.IsParameterExpression()).SelectMany(x => x.Validators)
.ToArray();
}
private static IEnumerable<IPropertyValidator> GetDependentRules<T, TProperty>(string expressionMemberName, Expression<Func<T, TProperty>> expression, IValidatorDescriptor descriptor)
{
var member = expression.IsParameterExpression() ? null : expressionMemberName;
var rules = descriptor.GetRulesForMember(member).OfType<PropertyRule>().SelectMany(x => x.DependentRules)
.SelectMany(x => x.Validators);
return rules;
}
}
}
And this is a test that should pass if you set the child validators to your classes and fail otherwise:
[Fact]
public void ChildValidatorsSet()
{
var _validator = new FluentRemortgageInstructionValidator();
_validator.ShouldHaveChildValidatorCustom(i => i.Property, typeof(FluentPropertyValidator));
_validator.ShouldHaveChildValidatorCustom(i => i.AdditionalInformation, typeof(FluentAdditionalInformationValidator));
}
Hope this helps!

C# reflection get implementing property of an interface property

I have an interface that I've defined a custom attribute on a property and I want to retrieve the relevant property from a derived instance of that interface.
public interface ITopicProcessor<T>
{
[TopicKey]
string TopicName { get; }
[OtherAttribute]
string OtherProperty { get; }
void Process(T message);
}
public class MyClassProcessor : ITopicProcessor<MyClass>
{
public string TopicName => "MyTopic";
public string OtherProperty => "Irrelevant";
public void Process(MyClass message)
{
}
}
I can get close with the following - the main issue is that the derived interface type doesn't seem to have the same custom attributes as the generic type definition. I'm pretty sure it's partly due to needing to use the underlying method implementation rather than use the property value directly
// iType is typeof(ITopicProcessor<MyClass>)
// I also have access to the generic type definition if need be - i.e. typeof(ITopicProcessor<>)
Func<Type, string> subscriberTypeToTopicKeySelector = iType =>
{
// Creating an instance via a dependency injection framework
var instance = kernel.Get(iType);
var classType = instance.GetType();
var interfaceMap = classType.GetInterfaceMap(iType);
// interfaceMap.InterfaceMethods contains underlying get_property method, but no custom attributes
var interfaceMethod = interfaceMap.InterfaceMethods
.Where(x => x.HasAttribute<TopicKeyAttribute>())
.ToList();
var classMethodInfo = interfaceMap.TargetMethods[Array.IndexOf(interfaceMap.InterfaceMethods, interfaceMethod)];
return classMethodInfo.Invoke(instance, BindingFlags.Default, null, null, CultureInfo.CurrentCulture)
.ToString();
};
Implementing an interface is not inheriting from a class. This is why such appributes do not propagate from interface to class. See: bradwilson.typepad.com/blog/2011/08/interface-attributes-class-attributes.html
But there are workarounds: Can a C# class inherit attributes from its interface?
Going off #thehennyy's comment I got something that not only works, but can handle the [TopicKey] attribute being applied to either a property or method. For my needs I only want it to appear once in an interface, but anyone else can extend this solution for their needs
subscriberTypeToTopicKeySelector = iType =>
{
var instance = kernel.Get(iType);
var classType = instance.GetType();
var interfaceMap = classType.GetInterfaceMap(iType);
var iTopicKeyPropertyGetMethods = iType.GetProperties()
.Where(x => x.HasAttribute<TopicKeyAttribute>())
.Select(x => x.GetMethod);
var iTopicKeyMethods = iType.GetMethods()
.Where(x => x.HasAttribute<TopicKeyAttribute>())
.Union(iTopicKeyPropertyGetMethods);
var indexOfInterfaceMethod = Array.IndexOf(interfaceMap.InterfaceMethods, iTopicKeyMethods.Single());
var classMethodInfo = interfaceMap.TargetMethods[indexOfInterfaceMethod];
return classMethodInfo.Invoke(instance, BindingFlags.Default, null, null, CultureInfo.CurrentCulture)
.ToString();
};

How do I setup MOQ to accept Any instances of a given Expression<T>?

I have the following interface that I want to mock:
public interface ISomeInterface
{
string GiveMe(Expression<Func<Person, bool>> predicate);
}
With the following Poco:
public class Person
{
public string Name { get; set; }
}
Then I am setting up my mock as:
[Test]
public void Run()
{
var expectedPredicate = It.IsAny<Expression<Func<Person, bool>>>();
var mock = new Mock<ISomeInterface>(MockBehavior.Strict);
mock
.Setup(m => m.GiveMe(expectedPredicate))
.Returns("Yo!");
var message = mock.Object.GiveMe(p => p.Name == string.Empty); // throws
}
But I am getting:
Invocation failed with mock behavior Strict. All invocations on the
mock must have a corresponding setup.
What am I missing here?
Don't assign the result of It.IsAny to an intermediate variable, use it inline:
mock.Setup(m => m.GiveMe(It.IsAny<Expression<Func<Person, bool>>>()))
.Returns("Yo!");
If you look at the Setup method, it actually takes an Expression parameter, Moq analyses this to determine what your intention is, by assigning the result of It.IsAny to an intermediate variable, Moq will not see the MethodCallExpression it is capable of understanding and instead will see a MemberExpression.
This results in Moq actually performing an equality comparison between the actual parameter and expectedPredicate variable rather than the It.IsAny check.

Substitute method in lambda expression

I am writing unit tests for a series of similar methods defined on a single interface (this is a precursor to refactoring). I'm finding that similar code shows up in multiple methods:
// Each line here shows up in a different test method.
mock.Setup(m => m.MethodA()).Returns(() => true);
mock.Setup(m => m.MethodB()).Returns(() => true);
mock.Setup(m => m.MethodC()).Returns(() => true);
I would like to create a single method into which I can pass the method to be tested, but am at a loss how to do this. I'd like something that looks like this:
// testMethod is some method defined on IMyInterface.
private Mock<IMyInterface> SetupMockObject(Func<bool> testMethod)
{
var mock = new Mock<MyInterface>();
mock.Setup(m => m.testMethod()).Returns(() => true);
return mock;
}
The call to this method would then look something like:
var configuredMockObject = SetupMockObject(MethodA);
Is this possible?
EDIT: An expression tree appears to be what I need - previously I didn't get the concept that you could pass lambda expressions around. I've pasted the solution below since it took me a bit of fiddling to figure this out, although both dBurner's and Servy's answers proved helpful.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Moq.Language.Flow;
using System;
using System.Linq.Expressions;
namespace ExampleTest
{
[TestClass]
public class TestClass
{
private Mock<IMyInterface> _mock;
private interface IMyInterface
{
bool MethodA();
bool MethodB();
}
private ISetup<IMyInterface, bool> SetupMockObject(Expression<Func<IMyInterface,bool>> lambda)
{
var mockSetup = _mock.Setup(lambda);
return mockSetup;
}
[TestInitialize]
public void Setup()
{
_mock = new Mock<IMyInterface>();
}
[TestMethod]
public void TestMethodA()
{
SetupMockObject(i => i.MethodA()).Returns(true);
// Proceed with act and assert.
}
[TestMethod]
public void TestMethodB()
{
SetupMockObject(i => i.MethodB()).Returns(true);
// Proceed with act and assert.
}
}
}
The lambda that you pass to it needs to have a parameter of the mocked type, whereas your current parameter accepts a parameterless delegate:
public static Mock<MyInterface> SetupMockObject<T>(
Func<MyInterface, bool> testMethod)
{
var mock = new Mock<MyInterface>();
mock.Setup(testMethod).Returns(() => true);
return mock;
}
This allows you to write:
var mock = SetupMockObject(m => m.MethodA());
and have the code be equivalent to
var mock = new Mock<MyInterface>();
mock.Setup(m => m.MethodA()).Returns(() => true);
You can use expression trees for this. Your CommonTest method should have a Expression<Func<bool>> parameter.
With this parameter type you can get the method name. after this you should construct another Expression that will represent m => m.MethodFromParameter.

Generics & static classes. Implement query helper method

Currently we implement a mapping service like this (the service uses automapper, and we make use of the projection feature on it for this part)
// Injected
// IGenericRepository<Entity> entityRepo
var query = this.entityRepo
.FindAll(a => a.Id == someId)
.Take(1);
var result = this.mappingService
.Map<Entity, EntityDto>(query)
.FirstOrDefault();
I'd like to create an extension that would allow me to do the following
var result = this.entityRepo
.FindAll(a => a.Id == someId)
.Take(1).Map<EntityDto>() <--- Entity inferred from repo type
.FirstOrDefault();
My current attempt:
public static class IQueryableExtensions
{
private static IMappingService mappingService;
// will need to be called in app initialization
public static void InitialiseMapper(IMappingService service)
{
mappingService = service;
}
public static IEnumerable<TDto> Map<TAttribute, TDto>(this IQueryable<TAttribute> value)
where TDto : class
where TAttribute : IEntity
{
return mappingService.Map<TAttribute, TDto>(value);
}
}
Thus currently my implementation would look like this.
var result = this.entityRepo
.FindAll(a => a.Id == someId)
.Take(1).Map<Entity,EntityDto>()
.FirstOrDefault();
Questions:
1) How would i go about inferring the entity type from the IQueryable object
2) I realize i cant create a constructor that takes parameters, when creating a static class. Is the way i init the mapper the best/only way?
I tried that with reflection. The constraints are only for demo. If you want to call the reflection code multiple times be sure to cache the final methodinfo.
void Main()
{
var a = new Entity[] {new Entity { name = "a"},new Entity { name = "b"}};
Console.WriteLine(a.Take(1).Map<EntityDto>());
}
public class Entity
{
public string name;
}
public class EntityDto
{
public string dtoname;
}
public static class EntityExtensions
{
public static IEnumerable<U> Map<T,U>(this IEnumerable<T> e) where T: Entity where U: EntityDto, new()
{
foreach(var a in e)
{
yield return new U() { dtoname = a.name };
}
}
public static IEnumerable<U> Map<U>(this IEnumerable<object> e)
{
var method = typeof(EntityExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(m => m.Name == "Map" && m.GetGenericArguments().Length == 2)
.Single();
method = method.MakeGenericMethod(e.GetType().GetGenericArguments()[0], typeof(U));
return method.Invoke(null, new object[] { e}) as IEnumerable<U>;
}
}
1) Currently, you simply can't do that in C#. The type inference is not good enough. You can either specify all type parameters or none of them.
Edit: If you really want the version with a single parameter, you have to delete the second type parameter, type the parameter as non-generic IQueryable and deal with it. One way of doing that would be to determine the generic IQueryable<T> type at runtime. However, this requires reflection. In the case of IQueryable, you can also use the query provider to get around the reflection.
2) You can use a static type constructor.
public static class MyExtensions {
static MyExtensions() {
//initialization goes here
}
}
This type constructor is even called thread-safe. However, if you manage to throw an exception here, you cannot access the MyExtensionsclass!

Categories