В моем проекте MVC3, Я использую интерфейс IUrlProvider для обертывания класса UrlHelper. В одном из действий контроллера у меня есть такой вызов:
string url = _urlProvider.Action("ValidateCode", new { code = "spam-and-eggs" });
Я хочу заглушить этот вызов метода в моем модульном тесте, который находится в отдельном проекте. Схема тестирования выглядит примерно так:
IUrlProvider urlProvider = MockRepository.GenerateStub<IUrlProvider>();
urlProvider.Stub(u => u.Action(
Arg<string>.Is.Equal("ValidateCode"),
Arg<object>.Is.Equal(new { code = "spam-and-eggs" }) ))
.Return("http://www.mysite.com/validate/spam-and-eggs");
К сожалению, Arg
не работает, потому что new {code = "spam-and-egg"}! = new {code = "spam-and-egg"}
, когда анонимные типы объявлены в разных сборках.
Итак, есть ли альтернативный синтаксис I можно ли использовать с Rhino Mocks для проверки соответствия значений полей анонимных объектов в сборках?
Или мне следует заменить объявления анонимных объектов классом, как это?
public class CodeArg
{
public string code { get; set; }
public override bool Equals(object obj)
{
if(obj == null || GetType() != obj.GetType())
{
return false;
}
return code == ((CodeArg)obj).code;
}
public override int GetHashCode()
{
return code.GetHashCode();
}
}
string url = _urlProvider.Action("ValidateCode",
new CodeArg { code = "spam-and-eggs" });
IUrlProvider urlProvider = MockRepository.GenerateStub<IUrlProvider>();
urlProvider.Stub(u => u.Action(
Arg<string>.Is.Equal("ValidateCode"),
Arg<CodeArg>.Is.Equal(new CodeArg { code = "spam-and-eggs" }) ))
.Return("http://www.mysite.com/validate/spam-and-eggs");
EDIT
Если бы мой модульный тест был в том же проекте, что и мой контроллер, сравнение анонимных объектов могло бы работать нормально. Поскольку они объявлены в отдельных сборках, они не будут равны, даже если у них одинаковые имена полей и значения. Сравнение анонимных объектов, созданных методами в разных пространствах имен, не кажется проблемой.
РЕШЕНИЕ
Я заменил Arg
на Arg
с использованием настраиваемого AbstractConstraint:
IUrlProvider urlProvider = MockRepository.GenerateStub<IUrlProvider>();
urlProvider.Stub(u => u.Action(
Arg<string>.Is.Equal("ValidateCode"),
Arg<object>.Matches(new PropertiesMatchConstraint(new { code = "spam-and-eggs" })) ))
.Return("http://www.mysite.com/validate/spam-and-eggs");
public class PropertiesMatchConstraint : AbstractConstraint
{
private readonly object _equal;
public PropertiesMatchConstraint(object obj)
{
_equal = obj;
}
public override bool Eval(object obj)
{
if (obj == null)
{
return (_equal == null);
}
var equalType = _equal.GetType();
var objType = obj.GetType();
foreach (var property in equalType.GetProperties())
{
var otherProperty = objType.GetProperty(property.Name);
if (otherProperty == null || property.GetValue(_equal, null) != otherProperty.GetValue(obj, null))
{
return false;
}
}
return true;
}
public override string Message
{
get
{
string str = _equal == null ? "null" : _equal.ToString();
return "equal to " + str;
}
}
}