How to get AutoMoqCustomization to use Strict MockBehavior?

Using AutoFixture with the AutoFixture.AutoMoq package, I sometimes find tests that were not set up to correctly verify what they wanted to check, but the problem was not detected due to the default (Loose) Mock behavior:

public interface IService { bool IsSomethingTrue(int id); } void Main() { var fixture = new Fixture() .Customize(new AutoMoqCustomization()); var service = fixture.Freeze<Mock<IService>>(); Console.WriteLine(service.Object.IsSomethingTrue(1)); // false } 

I want Mocks to be created with strict behavior, so we are forced to call Setup() for the methods we expect to call. I can do this for each individual layout:

 fixture.Customize<Mock<IService>>(c => c.FromFactory(() => new Mock<IService>(MockBehavior.Strict))); 

But after combing the source code for AutoMoqCustomization () and various ISpecimenBuilder and other implementations, I'm pretty lost to make all Mocks best initialize themselves with strict behavior. The structure seems very flexible and extensible, so I'm sure there is an easy way to do this - I just can't figure out how to do this.

+5
source share
2 answers

There is no simple built-in function that allows you to do something like this, but it should not be so difficult to do.

Essentially, you will need to modify the MockConstructorQuery so that it MockConstructorQuery constructor that takes the value MockBehavior and passes MockBehavior.Strict .

Now you cannot change this behavior in MockConstructorQuery , but this class contains only 9-10 lines of code, so you must create a new class that implements IMethodQuery using MockConstructorQuery as a starting point.

Similarly, you will also need to create custom ICustomization , which will be almost the same as AutoMoqCustomization , with the only exception that uses custom IMethodQuery with strict mock configuration instead of MockConstructorQuery . These are 7 more lines of code that you will need to write.

All that said, in my experience, using strict mocks is a bad idea . This will make your tests fragile and you will spend a lot of time fixing broken tests. I can only recommend that you do not, but now I have warned you; this is your foot.

+3
source

For those interested below, you can find the @MarkSeemann answer translated into code. I am sure that it does not cover all use cases, and it has not been heavily tested. But this should be a good starting point.

 using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Moq; using Ploeh.AutoFixture; using Ploeh.AutoFixture.AutoMoq; using Ploeh.AutoFixture.Kernel; namespace ConsoleApplication1 { public class StrictAutoMoqCustomization : ICustomization { public StrictAutoMoqCustomization() : this(new MockRelay()) { } public StrictAutoMoqCustomization(ISpecimenBuilder relay) { // TODO Null check params Relay = relay; } public ISpecimenBuilder Relay { get; } public void Customize(IFixture fixture) { // TODO Null check params fixture.Customizations.Add(new MockPostprocessor(new MethodInvoker(new StrictMockConstructorQuery()))); fixture.ResidueCollectors.Add(Relay); } } public class StrictMockConstructorMethod : IMethod { private readonly ConstructorInfo ctor; private readonly ParameterInfo[] paramInfos; public StrictMockConstructorMethod(ConstructorInfo ctor, ParameterInfo[] paramInfos) { // TODO Null check params this.ctor = ctor; this.paramInfos = paramInfos; } public IEnumerable<ParameterInfo> Parameters => paramInfos; public object Invoke(IEnumerable<object> parameters) => ctor.Invoke(parameters?.ToArray() ?? new object[] { }); } public class StrictMockConstructorQuery : IMethodQuery { public IEnumerable<IMethod> SelectMethods(Type type) { if (!IsMock(type)) { return Enumerable.Empty<IMethod>(); } if (!GetMockedType(type).IsInterface && !IsDelegate(type)) { return Enumerable.Empty<IMethod>(); } var ctor = type.GetConstructor(new[] { typeof(MockBehavior) }); return new IMethod[] { new StrictMockConstructorMethod(ctor, ctor.GetParameters()) }; } private static bool IsMock(Type type) { return type != null && type.IsGenericType && typeof(Mock<>).IsAssignableFrom(type.GetGenericTypeDefinition()) && !GetMockedType(type).IsGenericParameter; } private static Type GetMockedType(Type type) { return type.GetGenericArguments().Single(); } internal static bool IsDelegate(Type type) { return typeof(MulticastDelegate).IsAssignableFrom(type.BaseType); } } } 

Using

 var fixture = new Fixture().Customize(new StrictAutoMoqCustomization()); 
+1
source

Source: https://habr.com/ru/post/1237294/


All Articles