我可以动态地将数据注释添加到视图模型以进行单元测试吗?

时间:2014-06-06 20:42:09

标签: c# unit-testing tdd data-annotations

我要为自定义HtmlHelper编写一系列测试。

创建模拟视图模型(没有DataAnnotation):

    private sealed class MockLoginInputModel
    {
        public string Username { get; set; }
    }

然后有一个最简单的测试:

    [Test]
    public void SimplestLabel()
    {

        //arrange
        var sb = new StringBuilder();
        sb.Append(@"<label for=""Username"">");
        sb.Append(@"Username");
        sb.Append(@"</label>");
        var expected = sb.ToString();

        var html = HtmlHelperFactory.Create(new MockLoginInputModel());

        //act
        var result = html.WviLabelFor(m => m.Username);

        //assert
        var actualOutput = result.ToHtmlString();
        Assert.AreEqual(actualOutput, expected);
    }

最简单之后,我将编写一个测试,以查看DataAnnotation功能是否正常运行。

当然,我们可以使用一些数据注释创建另一个模拟模型,例如:

    private sealed class MockLoginInputModel
    {
        [DisplayName("Your Username: ")]
        public string Username { get; set; }
    }

但我们必须为不同的测试创建相当多的模型。

我们是否可以添加数据注释属性

[DisplayName("Your Username: ")])在测试方法中?

类似的东西:

    var model=new MockLoginInputModel();     
    model=AddDisplayName(model, "Your username:");             
    var html = HtmlHelperFactory.Create(model);

2 个答案:

答案 0 :(得分:2)

据我所知,你不能这样做。如果有人能证明我错了,那就太好了。

请参阅this questionthis question

答案 1 :(得分:1)

由于您正在运行单元测试,您可以执行以下操作:

public static readonly unformattedClass = "public class {0} {{ {1}public string MyString {{ get; set; }} }

单元测试:

[Test]
public void SimplestLabel()
{
   var className = "SimplestLabelClass";
   var dataAnnotation = "[DisplayName(\"Your Username: \")]";

   var formattedClass = string.Format(unformattedClass,
     className,
     dataAnnotation);

   var model = CreateDynamicModel(formattedClass, className);

   var html = HtmlHelperFactory.Create(model);
}

private object CreateDynamicModel(string formattedClass, string className)
{    
  object result;
  using (var csharp = new Microsoft.CSharp.CSharpCodeProvider())
  {
    var res = csharp.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters() 
        {  
            GenerateInMemory = true 
        }, 
        formattedClass
    );

    var classType = res.CompiledAssembly.GetType(className);

    result = Activator.CreateInstance(type);
  }

  return result;
}