Made the tests in MainPresenter be more specific & made the RandomBookGenerator methods not static to make it mockable.

This commit is contained in:
Iiro Krankka
2017-01-09 11:16:15 +02:00
parent feb54cefd5
commit b79e1230a9
12 changed files with 54 additions and 40 deletions

1
.idea/modules.xml generated
View File

@@ -5,7 +5,6 @@
<module fileurl="file://$PROJECT_DIR$/BookLibrary.iml" filepath="$PROJECT_DIR$/BookLibrary.iml" /> <module fileurl="file://$PROJECT_DIR$/BookLibrary.iml" filepath="$PROJECT_DIR$/BookLibrary.iml" />
<module fileurl="file://$PROJECT_DIR$/android-bdd-sample-using-cucumber.iml" filepath="$PROJECT_DIR$/android-bdd-sample-using-cucumber.iml" /> <module fileurl="file://$PROJECT_DIR$/android-bdd-sample-using-cucumber.iml" filepath="$PROJECT_DIR$/android-bdd-sample-using-cucumber.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" /> <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules> </modules>
</component> </component>
</project> </project>

View File

@@ -27,6 +27,8 @@ android {
dependencies { dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile 'org.mockito:mockito-core:2.5.5'
androidTestCompile 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0'
androidTestCompile ('com.android.support.test.espresso:espresso-core:2.2.1') { androidTestCompile ('com.android.support.test.espresso:espresso-core:2.2.1') {
exclude module: 'support-annotations' exclude module: 'support-annotations'
} }

View File

@@ -13,7 +13,6 @@ import static org.junit.Assert.assertTrue;
* Created by ironman on 02/09/16. * Created by ironman on 02/09/16.
*/ */
public class RecyclerViewAssertions { public class RecyclerViewAssertions {
public static ViewAssertion adapterItemCountEquals(int count) { public static ViewAssertion adapterItemCountEquals(int count) {
return new ItemCountAssertion(ItemCountAssertion.MODE_EQUALS, count); return new ItemCountAssertion(ItemCountAssertion.MODE_EQUALS, count);
} }

View File

@@ -19,7 +19,10 @@ import static com.codemate.booklibrary.RecyclerViewAssertions.adapterItemCountEq
import static com.codemate.booklibrary.RecyclerViewAssertions.adapterItemCountLowerThan; import static com.codemate.booklibrary.RecyclerViewAssertions.adapterItemCountLowerThan;
/** /**
* Created by ironman on 02/09/16. * Some really coarse UI tests.
*
* Check the MainPresenterTest for more specific tests that ensure correct books are
* returned.
*/ */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class MainActivityTest { public class MainActivityTest {

View File

@@ -39,7 +39,7 @@ public class Library {
return results; return results;
} }
public List<Book> findBooksByAuthor(String authorQuery) { private List<Book> findBooksByAuthor(String authorQuery) {
List<Book> results = new ArrayList<>(); List<Book> results = new ArrayList<>();
for (Book candidate : inventory) { for (Book candidate : inventory) {
@@ -54,7 +54,7 @@ public class Library {
return results; return results;
} }
public List<Book> findBooksByTitle(String titleQuery) { private List<Book> findBooksByTitle(String titleQuery) {
List<Book> results = new ArrayList<>(); List<Book> results = new ArrayList<>();
for (Book candidate : inventory) { for (Book candidate : inventory) {
@@ -69,7 +69,7 @@ public class Library {
return results; return results;
} }
public List<Book> findBooksByYear(String searchedYear) { private List<Book> findBooksByYear(String searchedYear) {
List<Book> results = new ArrayList<>(); List<Book> results = new ArrayList<>();
for (Book candidate : inventory) { for (Book candidate : inventory) {

View File

@@ -9,8 +9,6 @@ import java.util.List;
* Created by ironman on 02/09/16. * Created by ironman on 02/09/16.
*/ */
public class RandomBookGenerator { public class RandomBookGenerator {
private RandomBookGenerator() {}
private static final String[] SUBJECTS = { private static final String[] SUBJECTS = {
"Chicken", "Pig", "Hippo", "Dinosaur", "Giraffe", "Orangutan", "Chicken", "Pig", "Hippo", "Dinosaur", "Giraffe", "Orangutan",
"Bat", "Lion", "Daddy", "Grandpa", "Donald Trump", "Coffee", "Bat", "Lion", "Daddy", "Grandpa", "Donald Trump", "Coffee",
@@ -40,7 +38,7 @@ public class RandomBookGenerator {
* @param howMany how many random books should the generator generate. * @param howMany how many random books should the generator generate.
* @return a list that has as many books as the parameter howMany specifies. * @return a list that has as many books as the parameter howMany specifies.
*/ */
public static List<Book> generate(int howMany) { public List<Book> generate(int howMany) {
List<Book> books = new ArrayList<>(); List<Book> books = new ArrayList<>();
for (int i = 0; i < howMany; i++) { for (int i = 0; i < howMany; i++) {
@@ -53,7 +51,7 @@ public class RandomBookGenerator {
/** /**
* Generates a random book. * Generates a random book.
*/ */
public static Book randomBook() { public Book randomBook() {
String title = randomTitle(); String title = randomTitle();
String author = randomAuthor(); String author = randomAuthor();
Date date = randomDate(); Date date = randomDate();

View File

@@ -1,5 +1,6 @@
package com.codemate.booklibrary.ui; package com.codemate.booklibrary.ui;
import android.support.annotation.VisibleForTesting;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
@@ -9,11 +10,14 @@ import android.support.v7.widget.SearchView;
import com.codemate.booklibrary.data.Book; import com.codemate.booklibrary.data.Book;
import com.codemate.booklibrary.data.Library; import com.codemate.booklibrary.data.Library;
import com.codemate.booklibrary.R; import com.codemate.booklibrary.R;
import com.codemate.booklibrary.data.RandomBookGenerator;
import java.util.List; import java.util.List;
public class MainActivity extends AppCompatActivity implements MainView, SearchView.OnQueryTextListener { public class MainActivity extends AppCompatActivity implements MainView, SearchView.OnQueryTextListener {
private MainPresenter presenter; @VisibleForTesting
MainPresenter presenter;
private BookAdapter bookAdapter; private BookAdapter bookAdapter;
@Override @Override
@@ -23,8 +27,8 @@ public class MainActivity extends AppCompatActivity implements MainView, SearchV
initializeViews(); initializeViews();
presenter = new MainPresenter(this, new Library()); presenter = new MainPresenter(this, new Library(), new RandomBookGenerator());
presenter.loadAllBooks(); presenter.fetchBooks();
} }
private void initializeViews() { private void initializeViews() {

View File

@@ -1,5 +1,7 @@
package com.codemate.booklibrary.ui; package com.codemate.booklibrary.ui;
import android.support.annotation.VisibleForTesting;
import com.codemate.booklibrary.data.Book; import com.codemate.booklibrary.data.Book;
import com.codemate.booklibrary.data.Library; import com.codemate.booklibrary.data.Library;
import com.codemate.booklibrary.data.RandomBookGenerator; import com.codemate.booklibrary.data.RandomBookGenerator;
@@ -13,27 +15,27 @@ public class MainPresenter {
private final MainView mainView; private final MainView mainView;
private final Library library; private final Library library;
public MainPresenter(MainView mainView, Library library) { @VisibleForTesting
RandomBookGenerator bookGenerator;
public MainPresenter(MainView mainView, Library library, RandomBookGenerator bookGenerator) {
this.mainView = mainView; this.mainView = mainView;
this.library = library; this.library = library;
this.bookGenerator = bookGenerator;
} }
public void searchForBooks(String searchQuery) { public void searchForBooks(String searchQuery) {
List<Book> searchResults = library.search(searchQuery); List<Book> searchResults = library.search(searchQuery);
loadBooks(searchResults); mainView.showBooks(searchResults);
} }
public void loadAllBooks() { public void fetchBooks() {
// Populate the library with fake dummy data. In a real app // Populate the library with fake dummy data. In a real app
// we would have an interactor that would fetch the books from // we would have an interactor that would fetch the books from
// a real API. // a real API.
List<Book> books = RandomBookGenerator.generate(45); List<Book> books = bookGenerator.generate(45);
library.addBooks(books); library.addBooks(books);
loadBooks(library.getAllBooks()); mainView.showBooks(library.getAllBooks());
}
public void loadBooks(List<Book> books) {
mainView.showBooks(books);
} }
} }

View File

@@ -11,7 +11,7 @@ import java.util.List;
public class LibraryTest { public class LibraryTest {
@Test @Test
public void addMultipleBooks_PersistsThemInLibrary() { public void addMultipleBooks_PersistsThemInLibrary() {
List<Book> books = RandomBookGenerator.generate(3); List<Book> books = new RandomBookGenerator().generate(3);
Library library = new Library(); Library library = new Library();
library.addBooks(books); library.addBooks(books);

View File

@@ -14,7 +14,7 @@ import static org.junit.Assert.assertNotNull;
public class RandomBookGeneratorTest { public class RandomBookGeneratorTest {
@Test @Test
public void generatingRandomBooks_ReturnsNonEmptyBookList() { public void generatingRandomBooks_ReturnsNonEmptyBookList() {
List<Book> books = RandomBookGenerator.generate(15); List<Book> books = new RandomBookGenerator().generate(15);
assertEquals(15, books.size()); assertEquals(15, books.size());

View File

@@ -9,9 +9,12 @@ import org.junit.Test;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.sql.Date;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.mockito.Matchers.anyString; import static java.util.Collections.singletonList;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -19,36 +22,40 @@ import static org.mockito.Mockito.when;
* Created by ironman on 02/09/16. * Created by ironman on 02/09/16.
*/ */
public class MainPresenterTest { public class MainPresenterTest {
private static final List<Book> DUMMY_BOOKS = Arrays.asList(
new Book("Sample book one", "John Doe", Date.valueOf("2000-10-25")),
new Book("Sample book two", "Jane Doe", Date.valueOf("2016-01-01")),
new Book("Sample book three", "Some One", Date.valueOf("2005-12-12"))
);
@Mock @Mock
private MainView mainView; private MainView mainView;
@Mock @Mock
private Library library; private RandomBookGenerator bookGenerator;
private MainPresenter presenter; private MainPresenter presenter;
private List<Book> randomBooks;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
presenter = new MainPresenter(mainView, library); when(bookGenerator.generate(anyInt())).thenReturn(DUMMY_BOOKS);
randomBooks = RandomBookGenerator.generate(5); presenter = new MainPresenter(mainView, new Library(), bookGenerator);
} }
@Test @Test
public void searchForBooks_ShowsThemInUI() { public void searchForBooks_WhenSearchingByAuthorJohn_ShowsFirstBookInUI() {
when(library.search(anyString())).thenReturn(randomBooks); presenter.fetchBooks();
presenter.searchForBooks("test_search"); presenter.searchForBooks("John");
verify(mainView).showBooks(randomBooks); verify(mainView).showBooks(singletonList(DUMMY_BOOKS.get(0)));
} }
@Test @Test
public void loadAllBooks_ShowsThemInUI() { public void fetchBooks_LoadsAll_AndShowsThemInUI() {
when(library.getAllBooks()).thenReturn(randomBooks); presenter.fetchBooks();
presenter.loadAllBooks();
verify(mainView).showBooks(randomBooks); verify(mainView).showBooks(DUMMY_BOOKS);
} }
} }

View File

@@ -4,14 +4,14 @@ Feature: Book Search
Background: Background:
Given the library has a book with title "How to be awesome", written by "Iiro Krankka", published in 16 May 2016 Given the library has a book with title "How to be awesome", written by "Iiro Krankka", published in 16 May 2016
And a book with title "My life as an awesome guy", written by "Iiro Krankka", published in 27 July 2016 And a book with title "My life as an awesome guy", written by "Iiro Krankka", published in 27 July 2016
And a book with title "I think my teacher is an asshat", written by "John Doe", published in 01 January 2010 And a book with title "I think my teacher is cool", written by "John Doe", published in 01 January 2010
Scenario: List all books Scenario: List all books
When the customer wants to know all books in the library When the customer wants to know all books in the library
Then 3 books should be found Then 3 books should be found
And Book 1 should have the title "How to be awesome" And Book 1 should have the title "How to be awesome"
And Book 2 should have the title "My life as an awesome guy" And Book 2 should have the title "My life as an awesome guy"
And Book 3 should have the title "I think my teacher is an asshat" And Book 3 should have the title "I think my teacher is cool"
Scenario: Search books by year Scenario: Search books by year
When the customer searches for books published in year 2016 When the customer searches for books published in year 2016
@@ -39,5 +39,5 @@ Feature: Book Search
Examples: Examples:
| Title Search | Number of Results | Found Books | | Title Search | Number of Results | Found Books |
| "Awesome" | 2 | "How to be awesome" and "My life as an awesome guy" | | "Awesome" | 2 | "How to be awesome" and "My life as an awesome guy" |
| "asshat" | 1 | "I think my teacher is an asshat" | | "cool" | 1 | "I think my teacher is cool" |
| "How to be" | 1 | "How to be awesome" | | "How to be" | 1 | "How to be awesome" |