我正在测试一个MVC控制器。虽然我可以在测试运行后断言模型状态,但如果在将错误添加到ModelState时我可以使测试失败,我会更喜欢它。我的想法是模拟ModelState,但它没有setter。
有人知道如何在单元测试中听取ModelState.AddModelError
吗?
答案 0 :(得分:1)
围绕ModelState类包装类:
public class ModelStateWrapper : IValidationDictionary
{
private ModelStateDictionary ModelStateDictionary;
public ModelStateWrapper(ModelStateDictionary modelStateDictionary)
{
this.ModelStateDictionary = modelStateDictionary;
}
/// <summary>
/// Adds a validation error to the model state dictionary
/// </summary>
/// <param name="key">The key for the field</param>
/// <param name="errorMessage">The error message</param>
public void AddError(string key, string errorMessage)
{
this.ModelStateDictionary.AddModelError(key, errorMessage);
}
/// <summary>
/// Determines whether there are error messages in the model state dictionary
/// </summary>
public bool IsValid
{
get
{
return this.ModelStateDictionary.IsValid;
}
}
}
界面可能如下所示:
public interface IValidationDictionary
{
void AddError(string key, string errorMessage);
bool IsValid { get; }
}
然后在您的类中,在控制器的构造函数中分配ModelState:
public HomeController : IController
{
private IValidationDictionary validationDictionary;
public HomeController()
{
this.validationDictionary = new ModelStateWrapper(this.ModelState);
}
public ActionResult Index()
{
this.myService.CallSomething(this.validationDictionary)
}
}
当您将this.validationDictionary
的实例传递给服务时,它会从您的控制器中扩充原始ModelState
。
答案 1 :(得分:1)
修正了它。首次尝试使用:
var f = typeof(ViewDataDictionary).GetField("_modelState", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
var modelStateDictionary = MockRepository.GenerateMock<ModelStateDictionaryMock>();
f.SetValue(controller.ViewData, modelStateDictionary);
与
public abstract class ModelStateDictionaryMock : ModelStateDictionary
{
public abstract int Count { get; }
public abstract bool IsReadOnly { get; }
public abstract bool IsValid { get; }
public abstract ICollection<string> Keys { get; }
public abstract ICollection<ModelState> Values { get; }
public abstract ModelState this[string key] { get; set; }
public abstract void Add(KeyValuePair<string, ModelState> item);
public abstract void Add(string key, ModelState value);
public abstract void AddModelError(string key, Exception exception);
public abstract void AddModelError(string key, string errorMessage);
public abstract void Clear();
public abstract bool Contains(KeyValuePair<string, ModelState> item);
public abstract bool ContainsKey(string key);
public abstract void CopyTo(KeyValuePair<string, ModelState>[] array, int arrayIndex);
public abstract IEnumerator<KeyValuePair<string, ModelState>> GetEnumerator();
public abstract bool IsValidField(string key);
public abstract void Merge(ModelStateDictionary dictionary);
public abstract bool Remove(KeyValuePair<string, ModelState> item);
public abstract bool Remove(string key);
public abstract void SetModelValue(string key, ValueProviderResult value);
public abstract bool TryGetValue(string key, out ModelState value);
}
然而,由于以这种方式进行模拟无效,因此无法正常工作。所以我用Microsoft Fakes解决了它:
System.Web.Mvc.Fakes.ShimModelStateDictionary.AllInstances.AddModelErrorStringString =
(dictionary, key, errorMessage) =>
{
Assert.Fail(errorMessage);
};