#c# #moq #verify
#c# #moq #проверка
Вопрос:
При использовании Moq с Verify для утверждения, что определенный метод был вызван с указанными параметрами, возможен другой синтаксис; одним из них является синтаксис «It», например
mock.Verify(c => c.SomeMethod(It.Is<string>(s => s == ExpectedString)));
Здесь происходит то, что параметр, который SomeMethod
вызывается с помощью, проверяется на равенство с ExpectedString
. Другой возможный синтаксис — без «Этого»:
mock.Verify(c => c.SomeMethod(ExpectedString));
что должно дать тот же результат. Из того, что я смог найти на разных форумах, разница в том, что последнее является проверкой идентификации (ссылка равна) (за исключением типов значений).
Однако мой вопрос заключается в том, когда параметр относится к типу коллекции типов. В .NET Equals
on Collection<T>
просто наследуется от object
, поэтому следующая проверка:
mock.Verify(c => c.SomeMethod(new Collection<string> { ExpectedString }));
передача не должна быть возможной, учитывая, что коллекция создается при проверке и, следовательно, не может быть тем же экземпляром, который создается в производственном коде. Тем не менее, это работает, что указывает на то, что Moq выполняет CollectionAssert или что-то в этом роде, вопреки той информации, которую я мог найти.
Вот пример кода, который иллюстрирует поведение, тест проходит, но я думаю, что он должен завершиться неудачей, если Moq использовал сравнение reference equals.
[TestMethod]
public void Test()
{
var mock = new Mock<IPrint>();
const int ExpectedParam = 1;
var test = new TestPrinter { Printer = mock.Object, Expected = ExpectedParam };
test.Do();
mock.Verify(c => c.Print(new Collection<int> { ExpectedParam }));
}
public interface IPrint
{
void Print(Collection<int> numbers);
}
public class TestPrinter
{
public IPrint Printer { get; set; }
public int Expected { get; set; }
public void Do()
{
Printer.Print(new Collection<int> { Expected });
}
}
Кто-нибудь знает, ожидается ли такое поведение Moq (версия 4.1)? Было ли поведение изменено на каком-то уровне версии?
Ответ №1:
Это желаемое поведение и было добавлено в moq в январе 2009 года (версия 3.0.203.1).
Если moq находит an IEnumerable
, он использует SequenceEqual
для сравнения фактический аргумент и аргумент, используемый в настройке, в противном случае он просто использует Equals
.
Вот соответствующий фрагмент кода:
internal class ConstantMatcher : IMatcher
{
...
public bool Matches(object value)
{
if (object.Equals(constantValue, value))
{
return true;
}
if (this.constantValue is IEnumerable amp;amp; value is IEnumerable)
{
return this.MatchesEnumerable(value);
}
return false;
}
private bool MatchesEnumerable(object value)
{
var constValues = (IEnumerable)constantValue;
var values = (IEnumerable)value;
return constValues.Cast<object>().SequenceEqual(values.Cast<object>());
}
}