Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Monday, 19 September 2011

Gherkin in the language/parser of the .feature files

Cucumber is what SpecFlow is based off

image

The Feature is a story.

image

class file showing how to translate the Gherkin into something we can test.

Using MSTest here.

We are testing the whole stack here!  Albeit not the actual browser, but plugging into Bookshop and testing everything down from there.

Generating Reports

C:\Program Files (x86)\TechTalk\SpecFlow

| | # 
# Tuesday, 13 September 2011
( SpecFlow | TDD )

 

image

goes to ShoppingCart/Add post method then redirectToAction Index

image

checkout:

image

asdf

image

asdf

image

image

| | # 
( Autofac | Moq | SpecFlow )

Source is here: https://github.com/techtalk

SpecFlow aims at bridging the communication gap between domain experts and developers by binding business readable behavior specifications to the underlying implementation.

http://stackoverflow.com/questions/3443302/specflow-bdd-examples

https://github.com/techtalk/SpecFlow/wiki/Getting-Started – lots of links to tutorials and videos

image

App has only a few screens.  To see all books, you must search for nothing.

image

Testing the HomeController of the MVC layer

  • It returns a result to the default view
  • It produces a list of books in the Model (which the view will use).. using a faked out Service layer which just returns the 2 books

image

Details

image

image 

Code Snippet
        [TestMethod]
        public void WhenValidBookId_ShouldReturnViewWithBookForTheId()
        {
            // given
            var book = new Book();
            catalogServicesFake.Setup(m => m.GetBookDetails(1)).Returns(book);

            // when
            var result = controller.Details(1);

            // then
            var model = result.GetModel<DetailsModel>();
            Assert.AreEqual(book, model.Book);
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void WhenInvalidBookId_ShouldThrowArgumentException()
        {
            // given
            catalogServicesFake.Setup(m => m.GetBookDetails(1)).Returns((Book)null);

            // when
            controller.Details(1);

            // then: ArgumentException
        }
  • First test just tests that the /catalog/details/1   actually returns a viewresult  ie something happens
  • second just fakes a book
  • third is testing the null catch – this is actually testing business logic, and not just things are wired up right.
Code Snippet
public ActionResult Details(int id)
        {
            var book = catalogServices.GetBookDetails(id);
            if (book == null)
                throw new ArgumentException("Invalid book id", "id");

            var ratings = this.ratingsGateway.RetrieveRatings(book);

            decimal averageRating = ratingCalculator.CalculateRating(ratings ?? new Rating[0]);

            // US1_2_1: Call recommendationsGateway and process result
            string recommendedBooks = "";

            return View(new DetailsModel {
                Book = book,
                Rating = averageRating,
                RecommendedBooks = recommendedBooks
            });
        }

Search

Unit tests at this level (MVC) are really just testing something happens and doesn’t blow up.  And guard conditions are working ie null checks.

Code Snippet
namespace BookShop.UnitTests.CatalogControllerTests {
    [TestClass]
    public class SearchTests {
        private CatalogController controller;
        private Mock<ICatalogServices> catalogServicesFake;

        [TestInitialize]
        public void Setup() {
            catalogServicesFake = new Mock<ICatalogServices>();
            controller = new CatalogController(
                catalogServicesFake.Object,
                new Mock<IRatingsGateway>().Object,
                new Mock<IRatingCalculator>().Object,
                new Mock<IRecommendationsGateway>().Object);
        }

        [TestMethod]
        public void WhenSearchIsSuccessful_ShouldReturnViewResultToListView() {
            // given
            catalogServicesFake.Setup(m => m.Search("searchTerm")).Returns(new List<Book>());

            // when
            var result = controller.Search("searchTerm");

            // then
            Assert.AreEqual("List", ((ViewResult)result).ViewName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void WhenArgumentIsNull_ShouldThowException() {
            // given

            // when
            controller.Search(null);

            // then: ArgumentNullException
        }



        [TestMethod]
        public void WhenSearchResultIsEmpty_ShouldReturnViewWithEmptyList() {
            // given
            catalogServicesFake.Setup(m => m.Search("nonMatchingSearchTerm")).Returns(new List<Book>());

            // when
            var result = controller.Search("nonMatchingSearchTerm");

            // then
            var model = result.GetModel<List<Book>>();
            Assert.AreEqual(0, model.Count);
        }

        [TestMethod]
        public void WhenSearchResultIsNotEmpty_ShouldReturnViewWithListOfBooks() {
            // given
            var book1 = new Book();
            var book2 = new Book();
            catalogServicesFake.Setup(m => m.Search("searchTerm")).Returns(new List<Book> { book1, book2 });

            // when
            var result = controller.Search("searchTerm");

            // then
            var model = result.GetModel<List<Book>>();
            CollectionAssert.AreEquivalent(new List<Book> { book1, book2 }, model);
        }
    }
| | #