1

私はmvc 4でtddを調べています。

コンストラクターで作業単位インターフェイスを取るオーダーコントローラーがあります。

public OrdersController(IUnitOfWork db)
{
this.db = db;           
}

//
// GET: /Orders/
public ActionResult Index()
{                      
    return View(db.Orders.GetAll());
}

この Index() にはいくつかのテストがあります。

[TestClass]
    public class when_the_order_controller_index_action_executes
    {
        [TestMethod]
        public void it_should_render_the_default_view()
        {
            var uow = new Mock<IUnitOfWork>();
            var db = uow.Object;

            var orders = new List<Order>()
            {
                new Order{CreatedDate = DateTime.Now.AddMonths( -3),OrderID = Guid.NewGuid()},
                new Order{CreatedDate = DateTime.Now,OrderID = Guid.NewGuid()}
            };

            uow.Setup(r => r.Orders.GetAll())
                .Returns(orders);

            //arrange
            var controller = new OrdersController(db);

            //act
            var result = controller.Index() as ViewResult;

            //assert
            Assert.AreEqual("", result.ViewName);
        }

        [TestMethod]
        public void it_should_pass_orders_as_the_model()
        {
             var uow = new Mock<IUnitOfWork>();
            var db = uow.Object;

            var orders = new List<Order>()
            {
                new Order{CreatedDate = DateTime.Now.AddMonths( -3),OrderID = Guid.NewGuid()},
                new Order{CreatedDate = DateTime.Now,OrderID = Guid.NewGuid()}
            };


            uow.Setup(r => r.Orders.GetAll())
                .Returns(orders);

            //arrange
            var controller = new OrdersController(db);

            //act
            var model = ((ViewResult)controller.Index()).ViewData.Model as IEnumerable<Order>;

            //assert
            Assert.IsTrue(orders.Equals(model));
        }
    }

GetAll が返すことができるリストを作成するための 2 つのテストには、かなり多くのコードの重複があることに気付くでしょう...

両方のテストが呼び出すことができるリストを返すために再利用可能な関数を言うのは良い/悪い習慣ですか?

私が書いたテストに関する一般的なアドバイスは、tdd 愛を受け入れるようになったばかりなので、大歓迎です!

4

1 に答える 1

3

はい、一般的[TestInitialize]に、単体テストのフェーズで共通コードの初期化をすべてリファクタリングすることをお勧めします。また、非常に反復的であると感じる単体テストのすべての一般的な初期化/アサーション部分を再利用可能なメソッドに外部化することもできます。

したがって、あなたの特定の例では:

[TestClass]
public class when_the_order_controller_index_action_executes
{
    private IUnitOfWork db;
    private OrdersController sut;

    [TestInitialize]
    public void TestInitialize()
    {
        var uow = new Mock<IUnitOfWork>();
        this.db = uow.Object;

        var orders = new List<Order>()
        {
            new Order{ CreatedDate = DateTime.Now.AddMonths(-3),OrderID = Guid.NewGuid() },
            new Order{ CreatedDate = DateTime.Now,OrderID = Guid.NewGuid() }
        };

        uow.Setup(r => r.Orders.GetAll()).Returns(orders);

        this.sut = new OrdersController(db);
    }

    [TestMethod]
    public void it_should_render_the_default_view()
    {
        //act
        var result = this.sut.Index() as ViewResult;

        //assert
        Assert.AreEqual("", result.ViewName);
    }

    [TestMethod]
    public void it_should_pass_orders_as_the_model()
    {
        //act
        var model = ((ViewResult)this.sut.Index()).ViewData.Model as IEnumerable<Order>;

        //assert
        Assert.IsTrue(orders.Equals(model));
    }
}

ただし、通常は、各単体テストuow.Setup(r => r.Orders.GetAll()).Returns(orders);のフェーズが異なるため、フェーズの一部です。//arrangeそれはあなたが期待を定義する場所です。あなたの特定の例では、2 つのテストを 1 つのテストにマージします。

[TestClass]
public class when_the_order_controller_index_action_executes
{
    private IUnitOfWork db;
    private OrdersController sut;

    [TestInitialize]
    public void TestInitialize()
    {
        var uow = new Mock<IUnitOfWork>();
        this.db = uow.Object;

        var orders = new List<Order>()
        {
            new Order{ CreatedDate = DateTime.Now.AddMonths(-3),OrderID = Guid.NewGuid() },
            new Order{ CreatedDate = DateTime.Now,OrderID = Guid.NewGuid() }
        };

        uow.Setup(r => r.Orders.GetAll()).Returns(orders);

        this.sut = new OrdersController(db);
    }

    [TestMethod]
    public void it_should_render_the_default_view_and_pass_the_expected_view_model_to_it()
    {
        //act
        var actual = this.sut.Index();

        //assert
        Assert.IsInstanceOfType(actual, typeof(ViewModel));
        var viewResult = (ViewResult)actual;
        Assert.AreEqual(model, viewResult.Model);
    }
}
于 2013-06-16T14:39:09.080 に答える