使用C#从MOQ在VB中设置byref参数

时间:2016-09-19 13:35:34

标签: c# vb.net unit-testing moq

要测试的代码在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内调用时,参数meanRotationalSpeedMeanCompressorPowerMeanElectricalPower和结果返回0

ByRef MOQ中的参数,是否可以从C#到VB?

2 个答案:

答案 0 :(得分:0)

我想无论如何我应该回答这个问题。如果您使用的是最新版本的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,我不认为支持参数参数。 了解Moq 4中的新功能 https://github.com/moq/moq4

&#34;对out / ref参数的直观支持&#34;

另见 Assigning out/ref parameters in Moq

答案 1 :(得分:0)

这个扩展到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>;
    }
}

}