0

The code structure and classes emerge from this topic: C# Mock a Class With an Internal Property Setter

Here a summary of what I have.

I have the following Interface:

public interface IPosition
{
    // Some properties here which must be accessed in CalcValueChangeAtDate method.
    int Size { get; }
    ...

    double CalcValueChangeAtDate(DateTime fromDate, DateTime toDate);
}

And I implemented the interface in the class RealPosition like this:

public class RealPosition : IPosition
{
    /* IPosition implementation */
    public double CalcValueChangeAtDate(DateTime fromDate, DateTime toDate)
    {
        return CalcValueChangeAtDate(this, fromDate, toDate);
    }

    /* I created this static method with the idea to use the for mocked objects.
     * This way I would need to implement the logic only once and use it with real
     * and mocked objects*/
    public static double CalcValueChangeAtDate(IPosition pos, DateTime fromDate, DateTime toDate)
    {
        // Logic here must access properties of IPosition
    }
}

Further I created another class which uses the IPosition interface:

public class EquityCurveBuilder
{
    private static DataSeries CalcEquityCurve(List<IPosition> posDict)
    {
        DateTime fromDate;
        DateTime toDate;

        foreach (IPosition pos in posDict)
        {
            /* Here I want to call the implementation of IPosition.
             * However in my unit test posDict is a List of mocked IPositons. 
             * Simply because I don't have another choice. */
            double stockVal = pos.CalcValueChangeAtDate(fromDate, toDate);

            // Do something with stockVal
        }
    }
}

My test setup looks like this:

[Test]
public void RecalcOriginalEquityCurve()
{
    // Here I get a list of mocked IPositions
    List<IPosition> Positions   = ImporterTools.GetPositions(FilePath, FullPositionsCsv);

    // Execute Test
    DataSeries equityCurve      = EquityCurveBuilder.BuildEquityCurve(Positions);

    // Evaluate test results
    ...
}

public class ImporterTools
{
    public static List<IPosition> GetPositions(string path, string fileName)
    {
        // Import raw data and create a mocked IPosition
        Mock<IPosition> tmpPosMoq = new Mock<IPosition>();
        tmpPosMoq.Setup(v => v.CalcValueChangeAtDate(It.IsAny<DateTime>(), It.IsAny<DateTime>())).
                                                                            Returns( ??? );

        // Create a List and return it
    }
}

The problem is, that in the unit test all I have are mocked positions. But the CalcEquityCurve() method invokes CalcValueChangeAtDate() of IPostion. In order to test CalcEquityCurve() properly, CalcValueChangeAtDate() must return valid values. The return value depends on the arguments of the method. Hence the idea that the mocked object invokes the static method RealPosition.CalcValueChangeAtDate().

Now I am stuck with the ???. I simply don't have any idea what to write there so that my static method from the RealPosition class gets called when I call:

tmpPosMoq.Object.CalcValueChangeAtDate(fromDate, toDate);

Is it possible at all?

Thank you for your help! Konstantin

Community
  • 1
  • 1
Konstantin
  • 461
  • 1
  • 5
  • 13
  • Judging by your comment over `CalcValueChangeAtDate` I think you're missing the point of the mock. Make the mock return the simplest thing possible that lets you know whatever is using it has worked, which in this case would be a magic number as a `double`. Make it return something like `1.2345` and verify your system under test gets that value. – Patrick Quirk May 10 '16 at 19:29
  • You don't mock something if you want to call the actual implementation. It is very unclear what your goal is for the mock. – Crowcoder May 10 '16 at 19:36
  • @Crowcoder: Thank you for your input. I changed my description and hope that my goal is clear now. – Konstantin May 10 '16 at 20:46

1 Answers1

1

To answer your question, I think this is what you are asking for:

tmpPosMoq.Setup(v => v.CalcValueChangeAtDate(It.IsAny<DateTime>(), It.IsAny<DateTime>())).
                Returns( (DateTime dtfrom, DateTime dtto) => 
                {
                    return RealPosition.CalcValueChangeAtDate(tmpPosMoq.Object, dtfrom, dtto);
                });

But this is completely pointless. It is just a complex and convoluted way to call actual implementation that would be the exact same as if you did not mock it. Units tests are for testing business logic. Mocking is for providing fake but realistic values that would normally come from something that cannot be practically unit tested - database calls, web service calls, etc.

It is much more likely that something you have in here...

 // Logic here must access properties of IPosition

... is a candidate for mocking. But I do not see any dependencies being taken in your constructor so I can't even guess.

Crowcoder
  • 11,250
  • 3
  • 36
  • 45
  • That is exactly what I need. I did not know that I can simply use `v` as an argument. However when I do that I get the following three error messages: 1) Cannot convert lambda expression to type `double` because it is not a delegate type 2) Delegate `System.Func` does not take 2 arguments 3) The name `v` does not exist in the current context Any idea what I need to change to fix that? – Konstantin May 11 '16 at 19:39
  • PS: I am sorry, that I could not make my idea clear. I simply want to test `EquityCurveBuilder.CalcEquityCurve()`. I understand that I should return a specific value for a specific `fromDate`/`toDate` combination. But there so many that it will become very unrealistic to do that. Therefore I want to setup the mock in the way that it invokes an already tested method to simply calculate the needed value. – Konstantin May 11 '16 at 19:43
  • I guess you cannot use `v` in that context. Did you try `tmpPosMoq.Object` in place of it? – Crowcoder May 11 '16 at 19:54
  • Using `tmpPosMoq.Object` instead of `v` works like a charm. Thanks a lot! – Konstantin May 12 '16 at 03:52