Объект Moq, возвращающий другой объект Moq (модульное тестирование шаблона стратегии) - PullRequest
1 голос
/ 30 марта 2020

У меня есть класс, который использует шаблон стратегии, который я хотел бы протестировать. Он имеет зависимость от класса типа IResolver, который возвращает некоторый экземпляр класса типа ICalculator. Поэтому мне нужен объект Moq, который представляет распознаватель и при вызове возвращает другой объект Moq, представляющий калькулятор. У меня есть этот тест ниже:

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

А вот тестируемая функция

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

Модульный тест не пройден из-за какой-то ошибки с настройкой Moq:

System.ArgumentException: объект типа 'Yahtzee.Core.Enums.ScoreCategories' не может быть преобразован в тип 'Yahtzee.Core.Interfaces.IScoreCategoryCalculator'

Я не понимаю эту ошибку ( Я не получаю это, пока я фактически не запускаю юнит-тест Когда я отлаживаю тест, первая строка моей тестируемой функции работает правильно

IScoreCategoryCalculator scoreCalculator = _scoreCalculatorResolver.Resolve(category);

Так что мой пробный распознаватель разрешает некоторые IScoreCategoryCalculator. Следующая строка, однако, где происходит сбой. Если я сделаю QuickWatch в этой строке в Visual Studio, я смогу увидеть это:

Visual Studio Error Message

Есть идеи, что я здесь делаю неправильно? Может ли Moq вернуть другой объект Moq?

РЕДАКТИРОВАТЬ Пересматриваемые интерфейсы выглядят так:

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

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

РЕДАКТИРОВАНИЕ 2 Отображение полного стека

Трассировка стека: RuntimeType.TryChangeType (значение объекта, подшивка подшивки, культура CultureInfo, логическое значение needsSpecialCast) RuntimeType.CheckValue (значение объекта, подшивка подшивки, культураInfo, BindingFlags invokeAttr) MethodBase.CheckArguments , Binder Binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) RuntimeMethodInfo.InvokeArgumentsCheck (Object obj, BindingFlags invokeAttr, Binder binder, Object [] параметры, CultureInfo culture) RuntimeMethodInfo.Invoke (Object obj, binding Binding) Bindinder invinding Binding Binding параметры, культура CultureInfo) Delegate.DynamicInvokeImpl (Object [] args) Delegate.DynamicInvoke (Object [] args) Extensions.InvokePreserveStack (Delegate del, Object [] args) ReturnLazyValueResponse.RespondTo (вызов с вызовом) метод вызывания (метод вызова) катион) FindAndExecuteMatchingSetup.Handle (вызов-вызов, фиктивная ложь) IInterceptor.Intercept (вызов-вызов) Interceptor.Intercept (вызов IInvocation) AbstractInvocation.Proceed () UpperScoreManagerTests.UpperScoreManager_AddScoring_UpdatesScoreCorrectly () строка 18

...