2016-07-11 9 views
0

HtmlHelpersの結果を単体テストする方法はありますか?たとえば、カスタム入力用のHTMLマークアップを生成するヘルパーがあります(TagBuilderを内部で使用しています)。結果は文字列に変換してユニットテストで予想される文字列と比較する必要があるIHtmlStringです。しかし、これは非常に複雑になります。なぜなら、htmlでは属性の順序は気にしません。予想される文字列などをエスケープする必要があります。解決策:私はHtmlAglityPackを使用して単体テストを作成し始めました。コードは次のようになります。ASP.MVC:単体テストhtmlタグヘルパーの使用方法

var states = new[] { MultiStateInputState.Unknown, MultiStateInputState.Yes, MultiStateInputState.No }; 

var actual = Html.Abb().MultiStateInput(states).Name("myinput").ToHtmlString(); 
var doc = new HtmlDocument(); 
var actualTextInput = doc.DocumentNode.ChildNodes.First(n => n.Name == "input"); 

Assert.That(node, Is.Not.Null); 
Assert.That(node.Attributes, Is.Not.Null); 
Assert.That(node.Attributes, Is.Not.Empty); 
var attribute = node.Attributes.Single(a => a.Name == "name"); 
Assert.That(attribute, Is.Not.Null); 
Assert.That(attribute.Value, Is.EqualTo("myinput")); 

これは2つの文字列を比較するよりはるかに優れています。属性の順序などを気にする必要はありません。

+0

最終的には、htmlレイアウトを表す文字列を生成します。文字列の結果を比較することでテストできます。 –

答えて

1

私はこのquestionに答えました。これはHtmlHelpersをテストするための私の単体テストを示しています。

ここで私は偽物のためFakeItEasyを使用していますテスト

public static class LabelExtensionFixtures 
{ 
    [TestFixture] 
    public class should_return_label_with_required_info : MvcExtensionFixtureBase 
    { 
     private class TestClass 
     { 
      [Required] 
      public Guid Id { get; set; } 
     } 

     private MvcHtmlString _expectedResult; 
     private HtmlHelper<TestClass> _sut; 
     private MvcHtmlString _result; 

     [SetUp] 
     public void Given() 
     { 
      //arrange 
      _expectedResult = 
       MvcHtmlString.Create(
        "<label class=\"control-label col-md-2\" for=\"Id\">Id<span class=\"required\">*</span></label>"); 
      _sut = CreateHtmlHelper(new TestClass {Id = Guid.NewGuid()}); 

      //act 
      _result = _sut.LabelFor(model => model.Id, new { @class = "control-label col-md-2" }, "*"); 
     } 

     [Test] 
     public void Test() 
     { 
      //asert 
      Assert.That(_result.ToHtmlString(), Is.EqualTo(_expectedResult.ToHtmlString())); 
     } 
    } 
} 

    public abstract class MvcExtensionFixtureBase 
    { 
     protected HtmlHelper<T> CreateHtmlHelper<T>(T instance) 
     { 
      var viewDataDictionary = new ViewDataDictionary<T>(instance); 
      var viewContext = A.Fake<ViewContext>(); 
      A.CallTo(() => viewContext.ViewData).Returns(viewDataDictionary); 

      var viewDataContainer = A.Fake<IViewDataContainer>(); 
      A.CallTo(() => viewDataContainer.ViewData).Returns(viewDataDictionary); 

      return new HtmlHelper<T>(viewContext, viewDataContainer); 
     } 
    } 

ためのコードです。

テスト時にどのような問題が発生していますか?たぶんあなたのコードを投稿しますか?

+0

私が避けたいのは、あなたのような文字列リテラルを使用しています。 " "'私のポイントは、方法を見つけることです。解析されたHTMLをC#構造体に解析し、特定の部分だけをテストします。 –

+0

私はChrisのコメントに同意します。しかし、あなたがパースするときに設定されているなら、おそらくHtmlAgilityPackを使ってXMLフラグメントを解析することができます。非常に寛容なHTMLパーサを持っています。 – Fran

1

これをテストする方法の1つは、htmlからコントロールのC#表現に変換することです。これにより、生成されたHTMLを再解析してC#オブジェクトと照らし合わせることができます。そして、もちろん、属性オーダなどはもう重要ではありません。

サンプルテストは、次のようになります。パーサはおそらく非自明であるので、もちろん

[Fact] 
public void ControlIsGeneratedCorrectly() 
{ 
    var expected = new CustomControl { Foo = "Foo", Bar = 16 }; 

    var parser = new CustomControlParser(); 
    var model = new SomeViewModel { Foo = "Foo" }; 

    var actual = parser.Parse(Html.InputFor(model)); 

    Assert.AreEqual(expected.Foo, actual.Foo); 
    Assert.AreEqual(expected.Bar, actual.Bar); 
} 

を、これはあなたのテストに合併症を追加します。しかし、それは簡単にテストできます。いくつかのHTMLサンプルを与え、返されたC#オブジェクトが正しいプロパティを表示していることを確認してください。パーサーがあなたのhtmlヘルパーのテストを中断するケースを見つけたら、おそらくいくつかのテストケースをパーサに追加してそれらを修正する必要があります。

+0

パーサーは複雑さを増やすだけであり、実際にテストを満たしません。 HTMLヘルパーをテストしている場合、興味のある部分が返されます。したがって、 'expected'はテストモデルが与えられたときに返すと期待されるHTMLでなければならず、' actual'はそのテストモデルを渡すときに返される実際のHTMLになります。 –

+0

@ChrisPratt:もちろんですが、そのテストは正しく指定することは非常に困難です。属性の順序などは重要ではありません。このようなパーサーを経由すると、必要以上にHTMLヘルパーを必要とせずに、生成されたHTMLのいくつかの*プロパティ*(つまり、C#オブジェクトで表現できるオブジェクト)をテストするという付加価値がもたらされます。 –

+0

@ TomasLyckenありがとう、これは私が探しているものです。パーサの特定の例はありますか?どのようにC#オブジェクトにHTML文字列を変換する推奨された方法はありますか? –

関連する問題