Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Tuesday, 13 September 2011
( 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);
        }
    }
| | #