使用 C# 在 MOQ 中设置 VB 中的 byref 参数
Setup byref parameters in VB from MOQ with C#
要测试的代码在VB中是这样的。简化
Public Interface IFwCompressor
Function Calculate(ByVal condenserPower As Double,
ByVal evaporatingTemp As Double,
ByVal condensingTemp As Double,
ByRef rotationalSpeed As Double,
ByRef compressorPower As Double,
ByRef electricalPower As Double) As CalculationResult
Enum CalculationResult
ActivateNextCircuit = 3
Off = 2
Ok = 0
UnknownError = -1
MaxRps = -6
End Enum
End Interface
Public Class Compressor
Private ReadOnly _fwCompressor As IFwCompressor
Public Sub New(ByVal fwCompressor As IFwCompressor)
_fwCompressor = fwCompressor
End Sub
Public Function CalculateIntermittentResult(ByVal compressorInput As CompressorIntermittenInput) As StatusAndResult(Of CompressorStatus, CompressorResult)
Dim meanCompressorPower, meanRotationalSpeed, meanElectricalPower As Double
Dim result = _fwCompressor.CalculateIntermittentResult( _
compressorInput.RotationalSpeed,
compressorInput.RunningTimeFraction,
compressorInput.CompressorPower,
meanRotationalSpeed,
meanCompressorPower,
meanElectricalPower)
Return New StatusAndResult(Of CompressorStatus, CompressorResult)(
CompressorStatus.Ok,
New CompressorResult(CompressorRunMode.Intermittent,
meanRotationalSpeed,
meanCompressorPower,
meanElectricalPower))
End Function
我写的测试是这样的。 C# 和 MOQ 框架。
double meanRotationalSpeed = 15;
double meanCompressorPower = 1000;
double meanElectricalPower = 500;
fwCompressor.Setup(e => e.CalculateIntermittentResult(It.IsAny<double>(),
It.IsAny<double>(),
It.IsAny<double>(),
ref meanRotationalSpeed,
ref meanCompressorPower,
ref meanElectricalPower)).Returns(MaxRps);
我的问题是,当方法在 CalculateIntermittentResult
中调用时,参数 meanRotationalSpeed
、MeanCompressorPower
、MeanElectricalPower
和结果 return 0
?
ByRef
MOQ中的参数,是否可以从C#转为VB?
我想我还是应该回答这个问题。如果您使用的是最新版本的 Moq(版本 4),它支持 ref 参数。如果您查看文档,它支持在 ref 参数上设置,只要该参数与您在 System Under Tests 中调用它时传入的实例相同。
https://github.com/Moq/moq4/wiki/Quickstart
// ref arguments
var instance = new Bar();
// Only matches if the ref argument to the invocation is the same instance
mock.Setup(foo => foo.Submit(ref instance)).Returns(true);
如果您使用双精度数据类型,它必须与您在被测系统中使用的值相同。
//method under test
public int CallRef()
{
double d1 = 10;
var r1 = _foo.DoRef(ref d1);
return r1;
}
//test method
[TestMethod]
public void TestMethod1()
{
double dt = 10;
var fooStub = new Mock<IFoo>();
fooStub.Setup(x => x.DoRef(ref dt)).Returns(7);
var s = new S(fooStub.Object);
var r1 = s.CallRef();
}
只要 dt 为 10,ref 上的设置就应该有效。
如果您使用的是 Moq 3,我认为不支持 ref 参数。
查看 Moq 4 中的新功能
https://github.com/moq/moq4
"Intuitive support for out/ref arguments"
另见
Assigning out/ref parameters in Moq
此扩展最小起订量并将代码更改为
.OutCallback((double d1,
double d2,
double d3,
out double v1,
out double v2,
out double v3) =>
{
v1 = 15;
v2 = 1000;
v3 = 500;
}).Returns(IFwCompressor.CalculationResult.MaxRps);.OutCallback((double d1,
double d2,
double d3,
out double v1,
out double v2,
out double v3) =>
{
v1 = 15;
v2 = 1000;
v3 = 500;
}).Returns(IFwCompressor.CalculationResult.MaxRps);
namespace MoqExtensions
{
using Moq.Language;
using Moq.Language.Flow;
using System.Reflection;
public static class MoqExtensions
{
public delegate void OutAction<TOut>(out TOut outVal);
public delegate void OutAction<in T1, TOut>(T1 arg1, out TOut outVal);
public delegate void OutAction<in T1, TOut1, TOut2>(T1 arg1, out TOut1 outVal1, out TOut2 outVal2);
public delegate void OutAction<in T1, in T2, in T3, TOut1, TOut2, TOut3>(T1 arg1, T2 arg2, T3 agr3, out TOut1 outVal1, out TOut2 outVal2, out TOut3 outVal3);
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, TOut>(this ICallback<TMock, TReturn> mock, OutAction<TOut> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, T1, T2, T3, TOut1, TOut2, TOut3>(this ICallback<TMock, TReturn> mock, OutAction<T1, T2, T3, TOut1, TOut2, TOut3> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, T1, TOut1, TOut2>(this ICallback<TMock, TReturn> mock, OutAction<T1, TOut1, TOut2> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, T1, TOut>(this ICallback<TMock, TReturn> mock, OutAction<T1, TOut> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
private static IReturnsThrows<TMock, TReturn> OutCallbackInternal<TMock, TReturn>(ICallback<TMock, TReturn> mock, object action)
where TMock : class
{
mock.GetType()
.Assembly.GetType("Moq.MethodCall")
.InvokeMember("SetCallbackWithArguments", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock,
new[] { action });
return mock as IReturnsThrows<TMock, TReturn>;
}
}
}
要测试的代码在VB中是这样的。简化
Public Interface IFwCompressor
Function Calculate(ByVal condenserPower As Double,
ByVal evaporatingTemp As Double,
ByVal condensingTemp As Double,
ByRef rotationalSpeed As Double,
ByRef compressorPower As Double,
ByRef electricalPower As Double) As CalculationResult
Enum CalculationResult
ActivateNextCircuit = 3
Off = 2
Ok = 0
UnknownError = -1
MaxRps = -6
End Enum
End Interface
Public Class Compressor
Private ReadOnly _fwCompressor As IFwCompressor
Public Sub New(ByVal fwCompressor As IFwCompressor)
_fwCompressor = fwCompressor
End Sub
Public Function CalculateIntermittentResult(ByVal compressorInput As CompressorIntermittenInput) As StatusAndResult(Of CompressorStatus, CompressorResult)
Dim meanCompressorPower, meanRotationalSpeed, meanElectricalPower As Double
Dim result = _fwCompressor.CalculateIntermittentResult( _
compressorInput.RotationalSpeed,
compressorInput.RunningTimeFraction,
compressorInput.CompressorPower,
meanRotationalSpeed,
meanCompressorPower,
meanElectricalPower)
Return New StatusAndResult(Of CompressorStatus, CompressorResult)(
CompressorStatus.Ok,
New CompressorResult(CompressorRunMode.Intermittent,
meanRotationalSpeed,
meanCompressorPower,
meanElectricalPower))
End Function
我写的测试是这样的。 C# 和 MOQ 框架。
double meanRotationalSpeed = 15;
double meanCompressorPower = 1000;
double meanElectricalPower = 500;
fwCompressor.Setup(e => e.CalculateIntermittentResult(It.IsAny<double>(),
It.IsAny<double>(),
It.IsAny<double>(),
ref meanRotationalSpeed,
ref meanCompressorPower,
ref meanElectricalPower)).Returns(MaxRps);
我的问题是,当方法在 CalculateIntermittentResult
中调用时,参数 meanRotationalSpeed
、MeanCompressorPower
、MeanElectricalPower
和结果 return 0
?
ByRef
MOQ中的参数,是否可以从C#转为VB?
我想我还是应该回答这个问题。如果您使用的是最新版本的 Moq(版本 4),它支持 ref 参数。如果您查看文档,它支持在 ref 参数上设置,只要该参数与您在 System Under Tests 中调用它时传入的实例相同。
https://github.com/Moq/moq4/wiki/Quickstart
// ref arguments
var instance = new Bar();
// Only matches if the ref argument to the invocation is the same instance
mock.Setup(foo => foo.Submit(ref instance)).Returns(true);
如果您使用双精度数据类型,它必须与您在被测系统中使用的值相同。
//method under test
public int CallRef()
{
double d1 = 10;
var r1 = _foo.DoRef(ref d1);
return r1;
}
//test method
[TestMethod]
public void TestMethod1()
{
double dt = 10;
var fooStub = new Mock<IFoo>();
fooStub.Setup(x => x.DoRef(ref dt)).Returns(7);
var s = new S(fooStub.Object);
var r1 = s.CallRef();
}
只要 dt 为 10,ref 上的设置就应该有效。
如果您使用的是 Moq 3,我认为不支持 ref 参数。 查看 Moq 4 中的新功能 https://github.com/moq/moq4
"Intuitive support for out/ref arguments"
另见 Assigning out/ref parameters in Moq
此扩展最小起订量并将代码更改为
.OutCallback((double d1,
double d2,
double d3,
out double v1,
out double v2,
out double v3) =>
{
v1 = 15;
v2 = 1000;
v3 = 500;
}).Returns(IFwCompressor.CalculationResult.MaxRps);.OutCallback((double d1,
double d2,
double d3,
out double v1,
out double v2,
out double v3) =>
{
v1 = 15;
v2 = 1000;
v3 = 500;
}).Returns(IFwCompressor.CalculationResult.MaxRps);
namespace MoqExtensions
{
using Moq.Language;
using Moq.Language.Flow;
using System.Reflection;
public static class MoqExtensions
{
public delegate void OutAction<TOut>(out TOut outVal);
public delegate void OutAction<in T1, TOut>(T1 arg1, out TOut outVal);
public delegate void OutAction<in T1, TOut1, TOut2>(T1 arg1, out TOut1 outVal1, out TOut2 outVal2);
public delegate void OutAction<in T1, in T2, in T3, TOut1, TOut2, TOut3>(T1 arg1, T2 arg2, T3 agr3, out TOut1 outVal1, out TOut2 outVal2, out TOut3 outVal3);
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, TOut>(this ICallback<TMock, TReturn> mock, OutAction<TOut> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, T1, T2, T3, TOut1, TOut2, TOut3>(this ICallback<TMock, TReturn> mock, OutAction<T1, T2, T3, TOut1, TOut2, TOut3> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, T1, TOut1, TOut2>(this ICallback<TMock, TReturn> mock, OutAction<T1, TOut1, TOut2> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, T1, TOut>(this ICallback<TMock, TReturn> mock, OutAction<T1, TOut> action)
where TMock : class
{
return OutCallbackInternal(mock, action);
}
private static IReturnsThrows<TMock, TReturn> OutCallbackInternal<TMock, TReturn>(ICallback<TMock, TReturn> mock, object action)
where TMock : class
{
mock.GetType()
.Assembly.GetType("Moq.MethodCall")
.InvokeMember("SetCallbackWithArguments", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock,
new[] { action });
return mock as IReturnsThrows<TMock, TReturn>;
}
}
}