私はsitecoreの開発者です。 "EmailArticleController"コントローラのロジックをテストするためのサンプルSitecoreヘリックスユニットテストプロジェクトを作成したいインデックス()アクションメソッド:Sitecore.Mvc.Presentation.RenderingContextを使用してGlassControllerアクションをテストする方法
using Sitecore.Mvc.Presentation;
public class EmailArticleController : GlassController
{
//logic in below Index() method is what I want to test
public override ActionResult Index()
{
var _emailArticleBusiness = new EmailArticleBusiness();
var model = _emailArticleBusiness.FetchPopulatedModel;
var datasourceId = RenderingContext.Current.Rendering.DataSource;
_emailArticleBusiness.SetDataSourceID(datasourceId);
return View("~/Views/EmailCampaign/EmailArticle.cshtml", model);
}
//below is alternative code I wrote for mocking and unit testing the logic in above Index() function
private readonly IEmailArticleBusiness _businessLogic;
private readonly RenderingContext _renderingContext;
public EmailArticleController(IEmailArticleBusiness businessLogic, RenderingContext renderingContext)
{
_businessLogic = businessLogic;
_renderingContext = renderingContext;
}
public ActionResult Index(int forUnitTesting)
{
var model = _businessLogic.FetchPopulatedModel;
// *** do below two lines of logic somehow go into my Unit Testing class? How?
var datasourceId = _renderingContext.Rendering.DataSource;
_businessLogic.SetDataSourceID(datasourceId);
// ***
return View("~/Views/EmailCampaign/EmailArticle.cshtml", model);
}
}
OKこれは私が私のユニットテストクラスに持っているものです。
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Test_EmailArticleController_With_RenderingContext()
{
//Arrange
var businessLogicFake = new Mock<IEmailArticleBusiness>();
var model = new EmailArticleViewModel()
{
ArticleControl = new Article_Control() { },
Metadata = new Metadata() { }
};
businessLogicFake.Setup(x => x.FetchPopulatedModel).Returns(model);
// I'm not sure about the next 3 lines, how do I mock the RenderingContext and send it into the constructor, given that it needs a DataSource value too?
var renderingContext = Mock.Of<Sitecore.Mvc.Presentation.RenderingContext>(/*what goes here, if anything?*/) { /*what goes here, if anything?*/ };
EmailArticleController controllerUnderTest = new EmailArticleController(businessLogicFake.Object, renderingContext);
var result = controllerUnderTest.Index(3) as ViewResult;
Assert.IsNotNull(result);
}
}
は基本的に私はそれが(文字列)を持っていることを確認し、レンダリングコンテキストをモックとしたいデータソース値は "/ sitecore/home/..."のような値に設定され、私はそれをコントローラのコンストラクタに送信して(適切な方法であれば)、Index(int)メソッドを呼び出すと同時に、_businessLogic(この場合のインタフェースのみ)を確認します?)は、ビューを返す前に同じ値にdataSourceを設定しています。
これを実行するための正確なコードは何ですか?ありがとう!
ありがとう、あなたの答えは大変です!それは魅力のように働いた!!あなたは、「RenderingContext.Current.Rendering.DataSourceのような静的な依存関係にコードを密接に結合すると、コードを孤立してテストするのが難しくなる可能性があります。 ユニットテストのためにEmailArticleController()クラスにコードを絶対に追加する必要がある他の理由はありますか?あなたは、コンストラクタに何も送ることなく元のIndex()メソッドを単体テストできる方法がないことを暗示していますか? – user3034243
@ user3034243それはもっと設計の問題です。その静的依存関係を制御することはできません。つまり、通常の操作の外で必要になったときにどのように初期化されるかを制御できません。それはあなたが所有していないコードを制御できないため、孤立してテストすることが困難です。 SOLIDのようなトピックを読むと、メンテナンスしやすいクリーンなコードを設計することと、テストを含む方法をどのように関係させるのかを理解することができます。 – Nkosi
@ user3034243もう一つの可能な方法があるかもしれないと確信していますが、簡単にそれを正しく設計することができたら、それを捜すことができます。 – Nkosi