reg。 AutOfixtureを使用したHTMLヘルパーの単体テスト
-
29-10-2019 - |
質問
元の質問は次のとおりです。AutOfixtureを使用したHTMLヘルパーの単体テスト
元の質問を再開する必要があるかどうかはわかりません。しかし、私は解決されたように元の質問をマークして以来、新しい質問を作成することにしました。私がこれを間違えた場合はお詫びします。
私はマークの提案されたアプローチを使用していましたが、フリーズを使用している間は立ち往生しました。
以下は完全なソースコードです...テスト中のクラス:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcDemo2.Helpers
{
public static class Keys
{
public static readonly string SomeKey = "SomeKey";
}
public static class SampleHelpers
{
public static MvcHtmlString SampleTable(this HtmlHelper helper,
SampleModel model, IDictionary<string, object> htmlAttributes)
{
if (helper == null)
{
throw new ArgumentNullException("helper");
}
if (model == null)
{
throw new ArgumentNullException("model");
}
TagBuilder tagBuilder = new TagBuilder("table");
tagBuilder.MergeAttributes(htmlAttributes);
tagBuilder.GenerateId(helper.ViewContext.
HttpContext.Items[Keys.SomeKey].ToString());
return MvcHtmlString.Create(
tagBuilder.ToString(TagRenderMode.Normal));
}
}
}
public class SampleModel
{
}
}
ユニットテストは、httpcontext内の指定されたキーに対して予想どおりにHTMLを返すようにすることです
public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()
以下のようにフィクスチャを構成しました
var fixture = new Fixture().Customize(new AutoMoqCustomization());
次に、viewcontextでフリーズ:
var vc = fixture.Freeze<ViewContext>();
以下の例外を取得します:
エラー1テスト 'mvcdemo2.tests.controllers.samplehelperstsautofixture.sampletablehtmlhelper_whenkeyexistwithinhttpcontext_returnsexpedtml' failed:system.reflection.reflection.targetinvocationexception:recult of the invocation:remoling。 ---- System.NotimplementedException:メソッドまたは操作は実装されていません。 System.runtimemethodhandle._invokemethodfast(iruntimemethodinfoメソッド、オブジェクトターゲット、オブジェクト[]議論、signaturestruct&sig、methodattributes methodattributes、runtimetype typeowner)at system.runtimemethodhandle.invokemethodfast、smestimemethod fast、thationfact、thatugen 、runtimeType typeOwner)at System.Reflection.RuntimeMethodinfo.Invoke(オブジェクトOBJ、BindingFlags Invokeattr、Binder Binder、Objecters、CultureInfo Culture、Boolean SkipvisibilityChecks)at System.Reflection.Runtimethinfo.Invoke、Bindinvoke、bindinfflag、bindinfflags 、オブジェクト[]パラメーター、CultureInfo文化)
System.RuntimePropertyInfo.setValue(オブジェクトOBJ、オブジェクト値、バインディングフラグインボケート、バインダーバインダー、オブジェクト、culture、cultureinfo Culture)at System.RuntimePropertyInfo.setValue(オブジェクトOBJ、オブジェクト値、オブジェクト[]インデックス) ploeh.autofixture.kernel.autopropertiescommand1.Execute(T specimen, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.Postprocessor
1.PLOEH.AUTOFIXTURE.KERNEL.compositespecimenBuilder。2.MoveNext()
2.movenext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator
System.linq.Enumerable.d__a5で1.MoveNext()
1ソース)Ploeh.autofixture.kernel.compositespecimenbuilder.create(object request、ispecimencontext Context)at ploeh.autofixture.kernel.recursionguard.create )Ploeh.autofixture.kernel.seedignoringrelay.create(object request、ispecimencontext Context)at ploeh.autofixture.kernel.compositespecimenbuilder。
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable2.MoveNext()
2.movenext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator
System.linq.Enumerable.d__a5で1.MoveNext()
1ソース)ploeh.autofixture.kernel.compositespecimenbuilder.create(object request、ispecimencontextコンテキスト)ploeh.autofixture.kernel.postprocessor
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1.Create(Object request, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b) at System.Linq.Enumerable.WhereSelectListIterator
2.movenext()
System.linq.Enumerable.whereselectenumerableateratorで2.MoveNext()
1.movenext()
at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a5
at System.linq.Numerable.FirstordeFault [TSource](IENUMERABLE1 source) at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.SpecimenContext.Resolve(Object request) at Ploeh.AutoFixture.SpecimenFactory.CreateAnonymous[T](ISpecimenContext context, T seed) at Ploeh.AutoFixture.SpecimenFactory.CreateAnonymous[T](ISpecimenBuilderComposer composer, T seed) at Ploeh.AutoFixture.FixtureFreezer.Freeze[T](IFixture fixture, T seed)
2 SCOOPE、HTTPCONTEXTBASE HTTPCONTEXT)at System.Web.MVC.ViewContext.SetClientValidationEnabled(Boolean Enabled、Idictionary`2 Scope、HttpContextBase httpContext)at System.Web.MVC.ViewDatext.Set_ClientBalidatextext。
at MvcDemo2.Tests.Controllers.SampleHelpersTestsAutoFixture.SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml() in C:\Users\...:line 78 ----- Inner Stack Trace ----- at System.Web.HttpContextBase.get_Items() at System.Web.Mvc.ViewContext.ScopeCache.Get(IDictionary
プロパティViewContext.setClientValidationEnabledの値を設定しようとすると、失敗したようです。
私はこれに立ち往生しています。どんな考えも大いに感謝しています。
解決
まあ、あなたが内側のスタックトレースを考慮すると、あなたは例外がによってスローされていることに気付くでしょう HttpContextBase.Items
. 。リフレクションツールを使用して実装を調べると、この仮想メソッドがnotimplementedexceptionをスローすることがわかります - ポーラ違反について話してください。 BCLの多くのWeb抽象化はまさにそれを行いますが、これは本当に、本当に苦労しています。
それがあなたをさらに助けるかどうかはわかりませんが、このようなViewContextクラスの自動プロパティをオフにすることで、この特定の問題を乗り越えることができます:
fixture.Customize<ViewContext>(c => c.OmitAutoProperties());
他のヒント
マークに感謝します。 Autofixtureは非常に便利だと思いますが、MVCを単位テストすると、APIを適用するのが少し難しいと思います。それはおそらく私がまだAPIに慣れていないからでしょう。
と…。
fixture.Customize<ViewContext>(c => c.OmitAutoProperties());
var vc = fixture.Freeze<ViewContext>();
上記は正常に動作しますが、あなたが疑っていると、私がアイテムを追加しようとすると再び失敗します
vc.HttpContext.Items.Add(Keys.SomeKey, "foo");
例外:メソッドまたは操作は実装されていません。
httpcontextbaseのリフレクター...
public virtual IDictionary Items
{
get
{
throw new NotImplementedException();
}
}
だから私が考えることができる唯一の方法は、httpcontextbaseの独自の実装を作成することです
private class FakeHttpContext : HttpContextBase
{
private Dictionary<object, object> _items = new Dictionary<object, object>();
public override IDictionary Items { get { return _items; } }
}
以下は紛らわしいビットです。
fixture.Inject<HttpContextBase>(new FakeHttpContext());
var hc = fixture.CreateAnonymous<HttpContextBase>();
これら2つの行を交換すると(最初に匿名インスタンスを作成してから偽のインスタンスを挿入します)、エラーが発生します。
Autofixtureは、System.web.httpContextBaseからインスタンスを作成できませんでした。これは、おそらくパブリックコンストラクターがないためです。
これまでのところ、私はこのようなテストを思いつくことができます...
public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()
{
//Arrange
var fixture = new Fixture();
fixture.Customize<ViewContext>(c => c.OmitAutoProperties());
var vc = fixture.Freeze<ViewContext>();
fixture.Inject<HttpContextBase>(new FakeHttpContext());
var hc = fixture.CreateAnonymous<HttpContextBase>();
vc.HttpContext = hc;
vc.HttpContext.Items.Add(Keys.SomeKey, "foo");
var htmlHelper = fixture.CreateAnonymous<HtmlHelper>();
var sampleModel = fixture.CreateAnonymous<SampleModel>();
//Act
var result = SampleHelpers.SampleTable(htmlHelper, sampleModel, null).ToString();
//Assert
Assert.Equal("<table id=\"foo\"></table>", result);
}
また、テストに影響がないように見えるため、新しいAutomoQ customization()も削除されました。 Autofixtureに精通したら、より良いバージョンを考え出すことができるかもしれません。助けてくれてありがとう。