This function tries to retrieve the topic of the GitHub repository name using the GitHub API: https://api.github.com/repos/flutter/flutter/topics
public List<String> getTopics(String user, String repo){
GitHubRequest request = new GitHubRequest();
List<String> topic_list = new ArrayList<>();
try {
Repository repository = repositoryService.getRepository(user,repo);
String url = repository.getUrl().split("//")[1].split("api.github.com")[1];
request.setUri(url "/topics");
String result = new BufferedReader(new InputStreamReader(gitHubClient.getStream(request)))
.lines().collect(Collectors.joining("\n"));
JSONObject jsonObject = new JSONObject(result);
topic_list = Arrays.stream(jsonObject.get("names").toString().replace("[", "").replace("]", "").split(",")).collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}
return topic_list;
}
Is there a way to write a mockito test case for this? A beginner to testing, so thank you!
CodePudding user response:
First, you need to inject the mock object (repositoryService,gitHubClient) to your function.
If you use spring/spring boot, you can consider to use @Mock and @MockBean annotation. to mock the necessary bean.
The below code to create mock object manually.
RepositoryService fakeRs = Mockito.mock(RepositoryService.class);
GitHubClient fakeGHC = Mockito.mock(GitHubClient.class);
You also can use setter method to set mock object. setRepositoryService(fakeRs); setGitHubClient(fakeGHC);
The other way is using reflection utility to set private object.
ReflectionTestUtils.setField(yourService, "repositoryService", fakeRs);
ReflectionTestUtils.setField(yourService, "gitHubClient", fakeGHC);
After finish ingesting the mock object, you can write an test with expected behavior/data from mock object.
@Test
public void testGetTopics(){
// init mock object code in case setter/getter/reflection utils
Repository expectedRepository = createExampleRepository();
Mockito.when(repositoryService.getRepository(Mockito.anyString(),Mockito.anyString())
.thenReturn(expectedRepository);
// continue to fake gitHubClient with your expected data/ exceptions...
//call your method
List<?> data = yourService.getTopic("user","data");
Assertions.assertTrue(data!=null);
// you can write few assertion base on your fake datas
}
PS: Don't copy/paste the code, you will get compile errors. I am not using editor tool.
CodePudding user response:
You can mock repositoryService
and gitHubClient
to test various scenarios.
You can provide a package-level setter for these fields. It is a great idea to annotate it with Guava VisibleForTesting annotation.
Then you need to set mocks before the actual test on the instance.
Pseudocode for mocking
// First, we mock repository so we can return it from service
Repository repositoryMock = mock(Repository.class);
when(repository.getUrl()).thenReturn("https://...."); // You can return a URL or String, according to the mocked method's return type
// Then, we mock RepositoryService as well
RepositoryService repositoryServiceMock = mock(RepositoryService.class);
when(repositoryServiceMock.getRepository(anyString(), anyString()).thenReturn(repositoryMock);
// We mock gitHubService similarly
...
// After setting mock on the instance, we call the method and see if the results are expected
List<String> topics = getTopics("...", "...");
assertEquals(topics, ...);
// You can also assert interaction related things
verify(repositoryService).getRepository("a", "b"); // This is OK only if the service is called with "a" and "b" arguments