Moq object returning another Moq object (unit testing the strategy pattern)

Viewed 155

I have a class that is a consumer of the strategy pattern that I would like to unit test. It has a dependency on an IResolver type class that returns some instance of an ICalculator type class. So I need a Moq object that represents the resolver & when called, returns another Moq object that represents the calculator. I have this test below:

public void UpperScoreManager_AddScoring_UpdatesScoreCorrectly()
{
   var expectedScore = 10;
   var mockCaluclator = new Mock < IScoreCategoryCalculator > ();
   mockCaluclator.Setup(c => c.CalculateScore(It.IsAny < DiceSet > ()))
    .Returns(expectedScore);

   var mockResolver = new Mock < IScoreCategoryCalculatorResolver > ();
   mockResolver.Setup(r => r.Resolve(It.IsAny < ScoreCategories > ()))
    .Returns(mockCaluclator.Object);

   var manager = new Managers.ScoreManager.UpperScoreManager.UpperScoreManager(mockResolver.Object);

   manager.AddScoring(ScoreCategories.Aces, DiceSet.Create(new int[] { 1, 2, 3, 4, 5 }));

   Assert.Equal(expectedScore, manager.Score);
}

And here is the function being tested

public void AddScoring(ScoreCategories category, DiceSet diceSet)
{
    IScoreCategoryCalculator scoreCalculator = _scoreCalculatorResolver.Resolve(category);
    Score += scoreCalculator.CalculateScore(diceSet);
}

The unit test fails due to some error with the Moq setup:

System.ArgumentException : Object of type 'Yahtzee.Core.Enums.ScoreCategories' cannot be converted to type 'Yahtzee.Core.Interfaces.IScoreCategoryCalculator'

I don't understand this error (I don't receive this until I actually run the unit test). When I debug the test, the first line of my function under test works correctly

IScoreCategoryCalculator scoreCalculator = _scoreCalculatorResolver.Resolve(category);

So my mock resolver is resolving some IScoreCategoryCalculator. The next line, however, is where the failure occurs. If I do a QuickWatch on that line in Visual Studio I can see this:

Visual Studio Error Message

Any idea what I'm doing incorrectly here? Can Moq return another Moq object?

EDIT The interfaces being mocked look as so:

public interface IScoreCategoryCalculator
{
    ScoreCategories Type { get; }
    int CalculateScore(DiceSet diceSet);
}

public interface IScoreCategoryCalculatorResolver
{
    IScoreCategoryCalculator Resolve(ScoreCategories scoreCategory);
}

EDIT 2 Showing full stack

Stack Trace: RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast) RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr) MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) Delegate.DynamicInvokeImpl(Object[] args) Delegate.DynamicInvoke(Object[] args) Extensions.InvokePreserveStack(Delegate del, Object[] args) ReturnLazyValueResponse.RespondTo(Invocation invocation) MethodCall.Execute(Invocation invocation) FindAndExecuteMatchingSetup.Handle(Invocation invocation, Mock mock) IInterceptor.Intercept(Invocation invocation) Interceptor.Intercept(IInvocation invocation) AbstractInvocation.Proceed() IScoreCategoryCalculatorResolverProxy.Resolve(ScoreCategories scoreCategory) UpperScoreManager.AddScoring(ScoreCategories category, DiceSet diceSet) line 32 UpperScoreManagerTests.UpperScoreManager_AddScoring_UpdatesScoreCorrectly() line 18

0 Answers
Related