• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 測試驅動開發上的五大錯誤(3)

    發表于:2014-05-27來源:外刊It評論作者:不詳點擊數: 標簽:測試驅動開發
    18. productView, 19. navigationService, 20. productService, 21. basketService); 22. 23. // Act 24. productPresenter.Initialize(); 25. 26. // Assert 27. Assert.IsNotNull(productView.Product); 28. Asser

      18. productView,

      19. navigationService,

      20. productService,

      21. basketService);

      22.

      23. // Act

      24. productPresenter.Initialize();

      25.

      26. // Assert

      27. Assert.IsNotNull(productView.Product);

      28. Assert.IsTrue(productView.IsInBasket);

      29.}

      Test #2

      01.[TestMethod]

      02.public void InitializeWithValidProductIDReturnsView()

      03.{

      04. // Arrange

      05. var view = Mock.Create();

      06. Mock.Arrange(() => view.ProductID).Returns("spr-product");

      07.

      08. var mock = new MockProductPresenter(view);

      09.

      10. // Act

      11. mock.Presenter.Initialize();

      12.

      13. // Assert

      14. Assert.IsNotNull(mock.Presenter.View.Product);

      15. Assert.IsTrue(mock.Presenter.View.IsInBasket);

      16.}

      我相信Test #2是更容易理解的,不是嗎?而Test #1的可讀性不那么強的原因就是有太多的創建測試的代碼。在Test #2中,我把復雜的構建測試的邏輯提取到了ProductPresenter類里,從而使測試代碼可讀性更強。

      為了把這個概念說的更清楚,讓我們來看看測試中引用的方法:

      01.public void Initialize()

      02.{

      03. string productID = View.ProductID;

      04. Product product = _productService.GetByID(productID);

      05.

      06. if (product != null)

      07. {

      08. View.Product = product;

      09. View.IsInBasket = _basketService.ProductExists(productID);

      10. }

      11. else

      12. {

      13. NavigationService.GoTo("/not-found");

      14. }

      15.}

      這個方法依賴于View, ProductService, BasketService and NavigationService等類,這些類都要模擬或臨時構造出來。當遇到這樣有太多的依賴關系時,這種需要寫出準備代碼的副作用就會顯現出來,正如上面的例子。

      請注意,這還只是個很保守的例子。更多的我看到的是一個類里有模擬一、二十個依賴的情況。

      下面就是我在測試中提取出來的模擬ProductPresenter的MockProductPresenter類:

      01.public class MockProductPresenter

      02.{

      03. public IBasketService BasketService { get; set; }

      04. public IProductService ProductService { get; set; }

      05. public ProductPresenter Presenter { get; private set; }

      06.

      07. public MockProductPresenter(IProductView view)

      08. {

      09. var productService = Mock.Create();

      10. var navigationService = Mock.Create();

      11. var basketService = Mock.Create();

      12.

      13. // Setup for private methods

      14. Mock.Arrange(() => productService.GetByID("spr-product")).Returns(new Product());

      15. Mock.Arrange(() => basketService.ProductExists("spr-product")).Returns(true);

      16. Mock.Arrange(() => navigationService.GoTo("/not-found")).OccursOnce();

      17.

      18. Presenter = new ProductPresenter(

      19. view,

      20. navigationService,

      21. productService,

      22. basketService);

      23. }

      24.}

      因為View.ProductID的屬性值決定著這個方法的邏輯走向,我們向MockProductPresenter類的構造器里傳入了一個模擬的View實例。這種做法保證了當產品ID改變時自動判斷需要模擬的依賴。

      我們也可以用這種方法處理測試過程中的細節動作,就像我們在第二個單元測試里的Initialize方法里處理product==null的情況:

      01.[TestMethod]

      02.public void InitializeWithInvalidProductIDRedirectsToNotFound()

      03.{

      04. // Arrange

      05. var view = Mock.Create();

      06. Mock.Arrange(() => view.ProductID).Returns("invalid-product");

      07.

      08. var mock = new MockProductPresenter(view);

      09.

      10. // Act

      11. mock.Presenter.Initialize();

      12.

      13. // Assert

      14. Mock.Assert(mock.Presenter.NavigationService);

      15.}

      這隱藏了一些ProductPresenter實現上的細節處理,測試方法的可讀性是第一重要的。

    原文轉自:http://www.vaikan.com/top-5-tdd-mistakes/

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>