使用 IoC 的 MVC 2 验证属性单元测试
我目前正在为 ASP.NET MVC 2 控制器编写一些单元测试,并且在 MVC 2.0 验证属性方面遇到一些问题。有问题的验证属性使用存储库来检查当前数据源中是否不存在重复名称,并且我想在单元测试期间用假存储库替换该存储库。我正在使用温莎城堡,按照 这篇文章,它允许我在运行时替换存储库,但不确定如何在单元测试期间执行此操作。
大部分测试代码如下:
[TestMethod]
public void TestSaveDuplicateTitleNameReturnsValidationErrorView()
{
//Arrange
var titleRepository = new FakeTitleRepository();
var controller = new TitleController(titleRepository);
var selectedTitle = new Title();
selectedTitle.Name = "Fru";
//Act
var actual = controller.Save(selectedTitle);
来自控制器的代码示例如下:
public ActionResult Save(Title SelectedTitle)
{
if (TryValidateModel(SelectedTitle))
{
TitleRepository.Add(SelectedTitle);
TitleRepository.Save();
测试期间在控制器本身中使用的存储库是我已经通过的假存储库,但是当 TryValidateModel 触发并运行以下代码时它会导致异常,因为存储库为空:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class ValidTitleNameAttribute : ValidationAttribute
{
public ITitleRepository Repository { get; set; }
public override bool IsValid(object value)
{
bool isValid = true;
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
object name = properties.Find("Name", true).GetValue(value);
if (name == null)
{
return isValid = false;
}
var titles = Repository.GetAllTitles();
显然,在存储库属性中,我可以设置一个默认实例来引用具体存储库,这将防止测试期间出现异常,但这会破坏使用 IoC 容器的目的。解决这个问题的最佳方法是什么,是找到一种以某种方式模拟验证属性的方法,还是有一种方法 Windsor 可以在单元测试运行时注入假存储库?任何帮助/建议将不胜感激。
I am currently writing some unit tests for an ASP.NET MVC 2 controller and having some issues with the MVC 2.0 validation attributes. The validation attribute in question uses a repository to check that no duplicate names exist in the current data source, and I would like to replace this repository with a fake one during my unit test. I am using Castle Windsor, as per this article, which allows me to replace the repository at run time, but am not sure how I can do this during the unit test.
The bulk of the test code is this:
[TestMethod]
public void TestSaveDuplicateTitleNameReturnsValidationErrorView()
{
//Arrange
var titleRepository = new FakeTitleRepository();
var controller = new TitleController(titleRepository);
var selectedTitle = new Title();
selectedTitle.Name = "Fru";
//Act
var actual = controller.Save(selectedTitle);
A code sample from the controller is below:
public ActionResult Save(Title SelectedTitle)
{
if (TryValidateModel(SelectedTitle))
{
TitleRepository.Add(SelectedTitle);
TitleRepository.Save();
The repository being used in the controller itself during the test is my fake one that I have passed, but when the TryValidateModel fires and the following code is run then it causes an exception as the repository is null:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class ValidTitleNameAttribute : ValidationAttribute
{
public ITitleRepository Repository { get; set; }
public override bool IsValid(object value)
{
bool isValid = true;
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
object name = properties.Find("Name", true).GetValue(value);
if (name == null)
{
return isValid = false;
}
var titles = Repository.GetAllTitles();
Obviously in the repository property I could set a default instance to reference a concrete repository, which would prevent the exception during testing but that would defeat the purpose of using the IoC container. What would be the best way round this issue, would it be to find a way to mock the validation attribute in some way, or is there a way Windsor can inject the fake repository when the unit test runs? Any help/advice would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为最好的办法是为您的单元测试创建一个假的 DataAnnotationsModelValidator,它将在测试期间注入您的假存储库。您应该能够使其变得相当简单,以限制它导致单元测试出现任何问题的可能性。
I think the best thing to do would be to create a fake DataAnnotationsModelValidator for your unit test that will inject your fake repository during testing. You should be able to make it fairly simple so as to limit the chances of it causing any issues with your unit tests.