Использование moq для проверки вызова функции с параметрами param
У меня есть интерфейс ILogger с параметрами LogTrace (строковое значение, params object []). Теперь я хочу проверить, что LogTrace вызывается, а строка для журнала содержит некоторый идентификатор. Проблема в том, что ее можно назвать по-разному. Например.
1) LogTrace ( "MyString" + id)
2) LogTrace ( "MyString {0}", id)
и т.д.
Есть ли хороший способ с Moq проверить все сценарии? Я могу думать только о создании ручной работы, которая будет форматировать строку, которая будет доступна для проверки.
Ответы
Ответ 1
mock.Verify( m => m.LogTrace( It.IsAny<string>(), It.IsAny<object[]>() ) );
params object[]
передается методу как object[]
, так что вам просто нужно как-то сопоставить массив (как, например, выше, это принимает что-либо).
Если вам нужен больше контроля над списком, используйте It.Is
, который позволяет создать собственный предикат:
mock.Verify( m => m.LogTrace( It.IsAny<string>(),
It.Is<object[]>(ps =>
ps != null &&
ps.Length == 1 &&
ps[0] is int &&
(int)ps[0] == 5
) ) );
В этом примере показано, как проверить, не является ли список параметров не пустым и содержит 5
как единственный параметр типа int
.
Ответ 2
Вы можете попытаться использовать Callback
, но он будет достаточно запутанным (не тестированным):
var mock = new Mock<ILogger>();
string trace = null;
mock.Setup(l => l.LogTrace(It.IsAny<string>(), It.IsAny<object[]>()))
.Callback((s1, par) =>
{
trace = string.Format(s1, par);
});
//rest of the test
Assert.AreEqual(expected, trace);
Если ILogger
имеет небольшой интерфейс, вы можете подумать о том, чтобы запустить заглушку вручную (чтобы сохранить все строки, которые он должен регистрировать), и убедитесь, что в конце теста. Если вы регистрируете несколько строк, это будет более читаемой установкой.
Ответ 3
Я не думаю, что есть простой способ сделать то, что вам нужно здесь. Проблема в том, что вам необходимо убедиться, что определенная комбинация значений будет передана вашему методу, что приведет к множеству различных проверяемых сценариев:
- Строка содержит ID И параметры содержат ID-pass
- Строка содержит
ID И параметры не содержат ID-pass
- Строка не содержит
ID И параметры содержат ID = pass
- Строка не содержит ID AND
параметры не содержат ID-fail
Однако Moq не поддерживает подобные условные выражения между различными аргументами вашего проверяемого метода. Одним из возможных решений является проверка отсутствия id, а не его присутствие в любом аргументе. Попробуйте что-то вроде:
mock.Verify(m => m.LogTrace(
It.Is<string>(s => !s.Contains(id)),
It.Is<object[]>(o => !o.Contains(id))), Times.Never());
То, что мы здесь делаем, - это проверка того, выполняется ли условие сбоя, т.е. ваша строка не содержит идентификатора, а также массив объектов. Мы используем Times.Never(), чтобы убедиться, что эта ситуация никогда не произойдет.
Имейте в виду, однако, что код может быть не очевидным на первый взгляд; убедитесь, что вы правильно объяснили свое намерение, как только вы его напишете.