Skip to content

Failure when invoking a method with by-ref parameter & mockable return type on a mock with CallBase and DefaultValue.Mock configured #1249

Closed
@IanKemp

Description

NOTE: this is not a dupe of #1148 - my problem code is not using generics.

Apologies in advance if this is unclear - the tests in the repro solution I've attached should be more eloquent than my writing.

The repro uses AutoMoq because I haven't been able to trigger this issue in Moq directly, but the stack trace generated points directly to Moq as the culprit.

Describe the Bug

Given an object <OuterService>
That has a constructor dependency on an interface <InnerDependency>
And <InnerDependency> defines a method that accepts a parameter decorated with the in modifier
And <OuterService> defines a method that calls the previously-mentioned method on <InnerDependency>

When attempting to AutoMoq <OuterService> using the following:

var sut = new Fixture().Customize(new AutoMoqCustomization()).Create<<OuterService>>();

Moq 4.17.2 fails:

  Message: 
System.ArgumentException : Type must not be ByRef (Parameter 'type')

  Stack Trace: 
System.Dynamic.Utils.TypeUtils.ValidateType(Type type, String paramName, Boolean allowByRef, Boolean allowPointer)
System.Linq.Expressions.Expression.Constant(Object value, Type type)
Moq.MethodExpectation.CreateFrom(Invocation invocation)
Moq.Behaviors.ReturnBaseOrDefaultValue.Execute(Invocation invocation)
Moq.Return.Handle(Invocation invocation, Mock mock)
Moq.Mock.Moq.IInterceptor.Intercept(Invocation invocation)
Moq.CastleProxyFactory.Interceptor.Intercept(IInvocation underlying)
Castle.DynamicProxy.AbstractInvocation.Proceed()
<IInnerDependency>Proxy.DoSomething(Poco& poco)
<OuterService>.DoSomething(String input) line 16
<TestMethod>() line 26

but only if the in parameter on <IInnerDependency> is a non-primitive object type - if you use string, there is no exception (i.e. it works as expected)!

Based on the above stack trace it looks like this line is the problem. I think it needs to be changed to something like:

while (parameterTypes[i].HasElementType)
{
    parameterTypes[i] = parameterTypes[i].GetElementType();
}

arguments[i] = E.Constant(invocation.Arguments[i], parameterTypes[i]);

I haven't pulled this repo's source and tried the above, but a quick console app I whipped up (included in the repro) uses this approach and seems to work.

Scenario

Attached. There are 2 tests:

  • TestPoco: using a POCO as the in parameter (fails)
  • TestString: using a string as the in parameter (passes)

Expected Behavior

The first scenario (dependency with POCO as in parameter) works.

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions