0

The code to be tested looks like this in VB. Simplified

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

The test I've written like this. C# and the MOQ framework.

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);

My problem is that when the method gets invoke inside CalculateIntermittentResult, the parameters meanRotationalSpeed, MeanCompressorPower, MeanElectricalPower and the result return 0?

ByRef Parameters in MOQ, is it possible from C# to VB?

GSerg
  • 76,472
  • 17
  • 159
  • 346

2 Answers2

0

I think I should answer the question anyway. If you're using the latest version of Moq (Version 4), it has the support for ref arguments. If you look at the documentation, it supports setup on a ref argument as long as the argument is the same instance you pass in when it invoked within 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);

If you're using double data type, it has to be the same value you use in your system under test.

    //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(); 
    }

As long as the dt is 10, the setup on the ref should work.

If you're using Moq 3, I don't think the ref parameters has been supported. See what's new in Moq 4 https://github.com/moq/moq4

"Intuitive support for out/ref arguments"

see also Assigning out/ref parameters in Moq

Community
  • 1
  • 1
Spock
  • 7,009
  • 1
  • 41
  • 60
0

This extention to the MOQ and changing the code to

 .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>;
    }
}

}