JustMock - проверять значение переданного аргумента метода

Я использую фреймворк JustMock и имею следующее утверждение:

Mock.Assert(() => activityListenerMock.PeriodPassed(
  Arg.Matches<Period>(e => e.Length == expectedLength)));

Это терпит неудачу с загадочным сообщением:

Occurrence expectation failed. Expected at least 1 call. Calls so far: 0

Как я могу получить лучшее сообщение. Я хочу знать, с какой ценностью это называлось.

Метод на самом деле вызывается, но с неверным аргументом, потому что когда я изменяю утверждение на следующее, оно проходит:

Mock.Assert(() => activityListenerMock.PeriodPassed(
  Arg.IsAny<Period>()));

4 ответа

Решение

Один способ увидеть, какой аргумент был передан PeriodPassed это использовать DebugView JustMock

Место DebugView.IsTraceEnabled = true; в начале теста и добавить DebugView.CurrentState на часы. К концу вы увидите что-то мелодичное: Invocations: (ByRef ...).PeriodPassed("period value will go here") called 1 time; (signature: ...)

Значение периода будет показано в списке вызовов.

Еще один способ сделать это - извлечь средство сравнения в отдельную лямбду и использовать точку останова: Predicate<Period> matcher = e => e.Length == expectedLength; Mock.Assert(() => activityListenerMock.PeriodPassed( Arg.Matches<Period>(e => matcher(e))));

Теперь вы можете разместить точку останова внутри предиката и проверить значение e аргумент. Это работает, потому что теперь предикат является не выражением, а реальной функцией, так что теперь вы можете отлаживать его.

Как раз то, что написал Стефан Драгнев. Я использовал его идею, а затем добавил логику для проверки ввода. Если не ожидаемое значение, называется Assert.Fail(). Не уверен, что есть лучший способ, но это работает:

Mock.Arrange(() => _uowMock.Class.Add(
    Arg.Matches<ModelClass>(x => (CheckArgs(x, updated)))))
    .DoNothing().Occurs(3);

....

protected static bool CheckArgs(ModelClass x, int y)
{
    if (x.val != y)
    {
        Assert.Fail("Houston we have a problem");
    }

    return true;
}

Добавление дополнительной аранжировки раньше также работало для меня, но это очень забавно:

Mock.Arrange(() => activityListenerMock.PeriodPassed(Arg.IsAny<Period>())).
  DoInstead((Period p) => Console.WriteLine("Actual " + p.Length+" expected "+expectedLength));

Сегодня столкнулся с той же дилеммой и начал расширять идею Кшиштофа, некоторые с расширением. Это грубо, но функционально.

public static class JustMockExtensions {
        public static FuncExpectation<T> PrintParams<T, T1>(this FuncExpectation<T> mock) {
            return mock.DoInstead<T1, T>((arg1, arg2) => {
                string message = string.Empty;
                message += Process(arg1);
                message += Process(arg2);
                Console.WriteLine(message);
            });
        }

        private static string Process<T>(T obj) {
            if (typeof(T).IsEnum) {
                return Enum.GetName(typeof(T), obj);
            }
            return obj.ToString();
        }
    }

До сих пор использование этого способа позволяет ему перемещаться в нормальном потоке.

Mock.Arrange(() => foo.bar(Arg.IsAny<Widget>(), Arg.IsAny<WidgetTypeEnum>()))
                .PrintParams<Widget, WidgetTypeEnum>()
                .MustBeCalled();
Другие вопросы по тегам