Skip to content

Commit 975e4d8

Browse files
committed
Revise the ItByRef, set up more tests for the ref cases
1 parent 915b895 commit 975e4d8

File tree

5 files changed

+88
-19
lines changed

5 files changed

+88
-19
lines changed

Rubberduck.Main/ComClientLibrary/UnitTesting/Mocks/IComMock.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public interface IComMock
1717
object Object { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
1818

1919
[DispId(2)]
20-
void SetupWithReturns(string Name, object Value, [Optional, MarshalAs(UnmanagedType.Struct)] object Args);
20+
void SetupWithReturns(string Name, [MarshalAs(UnmanagedType.Struct)] object Value, [Optional, MarshalAs(UnmanagedType.Struct)] object Args);
2121

2222
[DispId(3)]
2323
void SetupWithCallback(string Name, [MarshalAs(UnmanagedType.FunctionPtr)] Action Callback, [Optional, MarshalAs(UnmanagedType.Struct)] object Args);

Rubberduck.Main/ComClientLibrary/UnitTesting/Mocks/ItByRef.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using Moq;
4-
5-
namespace Rubberduck.ComClientLibrary.UnitTesting.Mocks
1+
namespace Rubberduck.ComClientLibrary.UnitTesting.Mocks
62
{
73
public class ItByRef<T>
84
{
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Reflection;
3+
using ExpressiveReflection;
4+
5+
namespace Rubberduck.ComClientLibrary.UnitTesting.Mocks
6+
{
7+
public class ItByRefMemberInfos
8+
{
9+
public static Type ItByRef(Type type)
10+
{
11+
return typeof(ItByRef<>).MakeGenericType(type);
12+
}
13+
14+
public static MethodInfo Is(Type type)
15+
{
16+
return Reflection.GetMethodExt(ItByRef(type), nameof(ItByRef<object>.Is), type);
17+
}
18+
19+
public static FieldInfo Value(Type type)
20+
{
21+
return ItByRef(type).GetField(nameof(ItByRef<object>.Value));
22+
}
23+
}
24+
}

Rubberduck.Main/ComClientLibrary/UnitTesting/Mocks/SetupArgumentResolver.cs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ private Expression BuildPassByValueArgumentExpression(int index, SetupArgumentDe
236236

237237
private Expression BuildPassByRefArgumentExpression(int index, SetupArgumentDefinition definition, Type refType, Type elementType, ref Dictionary<ParameterExpression, object> forwardedArgs)
238238
{
239-
ParameterExpression parameterExpression;
239+
Expression parameterExpression;
240240
switch (definition.Type)
241241
{
242242
case SetupArgumentType.Is:
@@ -259,19 +259,11 @@ public void Test()
259259
// TODO: need to take care that the args passed into DynamicInvoke do not need to be ref'd - it should be
260260
// TODO: passed in as values then made ref within the expression tree.
261261
var name = $"p{index:00}";
262-
/*
263-
var forwardedArgExpression = Expression.Parameter(elementType, name);
264-
// forwardedArgs.Add(forwardedArgExpression, definition.Values[0]);
265-
266-
var conditionExpression = Expression.Lambda();
267-
var itByRefType = typeof(ItByRef<>).MakeGenericType(elementType);
268-
var itMemberInfo = Reflection.GetMethodExt(itByRefType, nameof(ItByRef<object>.Is));
269-
var itByRefExpression = Expression.Call(itMemberInfo, forwardedArgExpression, null);
270-
271-
parameterExpression = Expression.Field();
262+
var itByRef = ItByRefMemberInfos.Is(elementType).Invoke(null, new [] {definition.Values[0]});
263+
var forwardedArgExpression = Expression.Parameter(itByRef.GetType(), name);
264+
forwardedArgs.Add(forwardedArgExpression, itByRef);
265+
parameterExpression = Expression.Field(forwardedArgExpression, ItByRefMemberInfos.Value(elementType));
272266
return parameterExpression;
273-
*/
274-
return null;
275267
case SetupArgumentType.IsAny:
276268
var itRefType = typeof(It.Ref<>).MakeGenericType(elementType);
277269
var itFieldInfo = itRefType.GetField(nameof(It.IsAny));

RubberduckTests/ComMock/ItByRefTests.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Linq.Expressions;
35
using Moq;
46
using NUnit.Framework;
57
using Rubberduck.ComClientLibrary.UnitTesting.Mocks;
@@ -76,5 +78,60 @@ public void Basic_Ref_Setup_Returns()
7678
Assert.AreEqual(0, negativeActual);
7779
}
7880

81+
[Test]
82+
public void ItByRefMemberInfos_Is()
83+
{
84+
Assert.IsNotNull(ItByRefMemberInfos.Is(typeof(int)));
85+
}
86+
87+
[Test]
88+
[TestCase(nameof(ITestRef.DoInt), 1)]
89+
[TestCase(nameof(ITestRef.DoString), "abc")]
90+
public void Test_ByRef_Setup(string memberName, object value)
91+
{
92+
var definitions = new SetupArgumentDefinitions
93+
{
94+
SetupArgumentDefinition.CreateIs(value)
95+
};
96+
var resolver = new SetupArgumentResolver();
97+
var builder = new SetupExpressionBuilder(typeof(ITestRef), new List<Type>(), resolver);
98+
99+
var mock = new Mock<ITestRef>();
100+
var setupDatas = builder.CreateExpression(memberName, definitions);
101+
var setupData = setupDatas.First();
102+
103+
var called = false;
104+
void Action()
105+
{
106+
called = true;
107+
}
108+
109+
MockExpressionBuilder.Create(mock)
110+
.As(typeof(ITestRef))
111+
.Setup(setupData.SetupExpression, setupData.Args)
112+
.Callback(Action)
113+
.Execute();
114+
115+
object refParam = null;
116+
switch (memberName)
117+
{
118+
case nameof(ITestRef.DoInt):
119+
var refInt = (int) value;
120+
mock.Object.DoInt(ref refInt);
121+
refParam = refInt;
122+
break;
123+
case nameof(ITestRef.DoString):
124+
var refString = (string) value;
125+
mock.Object.DoString(ref refString);
126+
refParam = refString;
127+
break;
128+
default:
129+
Assert.Fail("Missing case for a member call");
130+
return;
131+
}
132+
133+
Assert.AreEqual(true, called);
134+
Assert.AreEqual(value, refParam);
135+
}
79136
}
80137
}

0 commit comments

Comments
 (0)