4

how to write a mockito test case for if...else statement which also includes exception test, I am quite confused about this. UserService is an interface

UserFactory.java

public class UserFactory { @Autowired private List<UserService> UserList; private final Map<String, UserService> UserMap = new HashMap<>(); @PostConstruct public void initUserMap() { for (final UserService user : UserList) { UserMap.put(user.getUserId(), user); } } public UserService getUser(String userId) { final UserService userService = UserMap.get(userlId); if (null == userService) { throw new IllegalArgumentException("user are not in the group"); } return userService; } } 

UserService(Interface)

public interface UserService{ String getUserName(); String getUserId(); } 

here is my test, but it is not correct...

@RunWith(MockitoJUnitRunner.class) public class UserServiceTest { @Mock private UserService userService; @InjectMocks private UserFactory UserFactory; private Map<String, User> UserMap; private String userId = "123"; @Before public void set_up(){ UserMap = new HashMap<>(); UserMap.put(userId, userService); } @Test public void getUser(){ when(UserMap.get(userId)).thenReturn(userService); userService actual = userServiceFactory.getUser(userId); assertEquals(UserMap.get(userId), actual); } } 
3
  • Maybe this post can help stackoverflow.com/questions/16243580/… Commented Jan 15, 2019 at 15:47
  • if (null == userService) { I assume. Right ? Commented Jan 15, 2019 at 16:12
  • @davidxxx, thanks David, I have updated the question Commented Jan 15, 2019 at 16:13

1 Answer 1

5

1) You write an unit test, not a sliced test or an integration test. So here Spring Boot doesn't matter as you don't need to load a container to test the logic of your component.
You can read my question/answer about this field if you are interested in.

2) A branch (if/else) in the logic means that you have multiple scenarios.
Distinct scenarios mean generally distinct test methods and meaningful names.
You can also rely on the given/when/then idiom.

3) Since in your test the input information for the branch is provided by the mock, it also means that you will register distinct behaviors for the mock in each test method.

4) UserService doesn't need to be mocked. It has to be a value returned by the mock not the mock itself. Here you have to mock the Map.

5) You test UserFactory, so you have to name it UserFactoryTest .

For example :

@RunWith(MockitoJUnitRunner.class) public class UserFactoryTest { @Mock private Map<String, User> UserMap; @InjectMocks private UserFactory UserFactory; private String userId = "123"; @Test public void getUser(){ when(UserMap.get(userId)).thenReturn(userService); userService actual = userServiceFactory.getUser(userId); assertEquals(UserMap.get(userId), actual); } @Test public void getUser_with_unknown_userId(){ Assertions.assertThrows(IllegalArgumentException.class, ()-> userServiceFactory.getUser(userId)); } } 

You notice that in the second case I don't register any behavior for the mock.
By default Mockito will return null and actually it is what I need to provoke the exception. So it is fine.
Note also that I wrote the assertion by relying on the JUnit 5 library and not the JUnit 4 library that you seem to use according the used runner.
You should consider to switch to JUnit 5 for new tests.

Sign up to request clarification or add additional context in comments.

1 Comment

I encountered another issue, when I run the first test, org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'. Does it mean I get a value from the map is not a method? how to solve this problem?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.