$30 off During Our Annual Pro Sale. View Details »

Clean Architecture & TDD

Clean Architecture & TDD

Clean Architecture & TDD @Android Test Night #1
https://testnight.connpass.com/event/63753/

Fumihiko Shiroyama

September 20, 2017
Tweet

More Decks by Fumihiko Shiroyama

Other Decks in Technology

Transcript

  1. About Me • Fumihiko Shiroyama • Android App Developer •

    Unit Test Enthusiast • https://github.com/srym
  2. TDD is great! because... • Focus on I/O • Less

    reworking • Force Unit Testing
  3. Blank Implementation public class RestGitHubDataSource implements RemoteGitHubDataSource { @Override public

    Single<List<Repo>> listRepos(@NonNull String user) { return Single.error(new RuntimeException()); } }
  4. Blank Implementation public class RestGitHubDataSource implements RemoteGitHubDataSource { @Override public

    Single<List<Repo>> listRepos(@NonNull String user) { return Single.error(new RuntimeException()); } }
  5. Test First public class RestGitHubDataSourceTest { private RestGitHubDataSource dataSource; @Before

    public void setUp() throws Exception { dataSource = new RestGitHubDataSource(); } @Test public void listRepos() throws Exception { // implement here! } }
  6. Test First @Test public void listRepos() throws Exception { List<Repo>

    repos = restGitHubDataSource.listRepos("srym") .test() .await() .assertNoErrors() .assertComplete() .values() .get(0); assertThat(repos).isNotNull(); }
  7. Minimum Implementation public class RestGitHubDataSource implements RemoteGitHubDataSource { private final

    GitHubService gitHubService; @Inject public RestGitHubDataSource(GitHubService gitHubService) { this.gitHubService = gitHubService; } @Override public Single<List<Repo>> listRepos(@NonNull String user) { return gitHubService.listRepos(user); } }
  8. Minimum Implementation public class RestGitHubDataSource implements RemoteGitHubDataSource { private final

    GitHubService gitHubService; @Inject public RestGitHubDataSource(GitHubService gitHubService) { this.gitHubService = gitHubService; } @Override public Single<List<Repo>> listRepos(@NonNull String user) { return gitHubService.listRepos(user); } }
  9. Minimum Implementation public class RestGitHubDataSource implements RemoteGitHubDataSource { private final

    GitHubService gitHubService; @Inject public RestGitHubDataSource(GitHubService gitHubService) { this.gitHubService = gitHubService; } @Override public Single<List<Repo>> listRepos(@NonNull String user) { return gitHubService.listRepos(user); } }
  10. MockWebServer Dispatcher dispatcher = new Dispatcher() { @Override public MockResponse

    dispatch(RecordedRequest request) throws InterruptedException { return new MockResponse().setResponseCode(404); } }; mockWebServer.setDispatcher(dispatcher); mockWebServer.start();
  11. MockWebServer @Override public MockResponse dispatch(RecordedRequest request) throws InterruptedException { if

    (request == null || request.getPath() == null) { return new MockResponse().setResponseCode(400); } if (request.getPath().matches("/users/.+/repos")) { return new MockResponse() .setBody(readJsonFromResources("users_repos.json")) .setResponseCode(200); } return new MockResponse().setResponseCode(404); }
  12. MockWebServer @Override public MockResponse dispatch(RecordedRequest request) throws InterruptedException { if

    (request == null || request.getPath() == null) { return new MockResponse().setResponseCode(400); } if (request.getPath().matches("/users/.+/repos")) { return new MockResponse() .setBody(readJsonFromResources("users_repos.json")) .setResponseCode(200); } return new MockResponse().setResponseCode(404); }
  13. MockWebServer @Override public MockResponse dispatch(RecordedRequest request) throws InterruptedException { if

    (request == null || request.getPath() == null) { return new MockResponse().setResponseCode(400); } if (request.getPath().matches("/users/.+/repos")) { return new MockResponse() .setBody(readJsonFromResources("users_repos.json")) .setResponseCode(200); } return new MockResponse().setResponseCode(404); }
  14. MockWebServer @Override public MockResponse dispatch(RecordedRequest request) throws InterruptedException { if

    (request == null || request.getPath() == null) { return new MockResponse().setResponseCode(400); } if (request.getPath().matches("/users/.+/repos")) { return new MockResponse() .setBody(readJsonFromResources("users_repos.json")) .setResponseCode(200); } return new MockResponse().setResponseCode(404); } Talk about this later
  15. Read JSON from file private String readJsonFromResources(@NonNull String fileName) {

    InputStream inputStream = getClass().getClassLoader().getResourceAsStream(fileName); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder stringBuilder = new StringBuilder(); try { String buffer; while ((buffer = bufferedReader.readLine()) != null) { stringBuilder.append(buffer); } } catch (IOException e) { fail(e.getMessage(), e); } return stringBuilder.toString(); }
  16. Fix Test @Before public void setUp() throws Exception { //

    abbr. dataSource = new RestGitHubDataSource(gitHubService); } @Test public void listRepos() throws Exception { List<Repo> repos = restGitHubDataSource.listRepos("srym") .test() .await() .assertNoErrors() .assertComplete() .values() .get(0); assertThat(repos).isNotNull(); // abbr. }