Cho đến bây giờ các câu trả lời từ SO đã hoàn toàn thỏa mãn các vấn đề của tôi. Tôi đang học thử nghiệm đơn vị với Junit và Mockito và tôi muốn kiểm tra lớp dịch vụ của mình, một phần của ứng dụng web Spring của tôi. Tôi đã đọc nhiều bài hướng dẫn và bài viết và tôi vẫn gặp vấn đề khi viết các bài kiểm tra đơn vị thích hợp cho lớp dịch vụ của mình. Tôi muốn biết câu trả lời cho câu hỏi của tôi, nhưng trước tiên tôi dán một số mã:Thử nghiệm đơn vị dịch vụ mùa xuân bằng cách sử dụng mockito
lớp Service
public class AccountServiceImpl implements AccountService {
@Autowired
AccountDao accountDao, RoleDao roleDao, PasswordEncoder passwordEncoder, SaltSource saltSource;
@PersistenceContext
EntityManager entityManager;
public Boolean registerNewAccount(Account newAccount) {
entityManager.persist(newAccount);
newAccount.setPassword(passwordEncoder.encodePassword(newAccount.getPassword(), saltSource.getSalt(newAccount)));
setRoleToAccount("ROLE_REGISTERED", newAccount);
return checkIfUsernameExists(newAccount.getUsername());
}
public void setRoleToAccount(String roleName, Account account) {
List<Role> roles = new ArrayList<Role>();
try {
roles.add(roleDao.findRole(roleName));
} catch(RoleNotFoundException rnf) {
logger.error(rnf.getMessage());
}
account.setRoles(roles);
}
public Boolean checkIfUsernameExists(String username) {
try {
loadUserByUsername(username);
} catch(UsernameNotFoundException unf) {
return false;
}
return true;
}
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
Account loadedAccount = accountDao.findUsername(username);
return loadedAccount;
} catch (UserNotFoundException e) {
throw new UsernameNotFoundException("User: " + username + "not found!");
}
}
}
dở dang lớp thử nghiệm của tôi
@RunWith(MockitoJUnitRunner.class)
public class AccountServiceImplTest {
private AccountServiceImpl accountServiceImpl;
@Mock private Account newAccount;
@Mock private PasswordEncoder passwordEncoder;
@Mock private SaltSource saltSource;
@Mock private EntityManager entityManager;
@Mock private AccountDao accountDao;
@Mock private RoleDao roleDao;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
accountServiceImpl = new AccountServiceImpl();
ReflectionTestUtils.setField(accountServiceImpl, "entityManager", entityManager);
ReflectionTestUtils.setField(accountServiceImpl, "passwordEncoder", passwordEncoder);
ReflectionTestUtils.setField(accountServiceImpl, "saltSource", saltSource);
ReflectionTestUtils.setField(accountServiceImpl, "accountDao", accountDao);
ReflectionTestUtils.setField(accountServiceImpl, "roleDao", roleDao);
}
@Test
public void testRegisterNewAccount() {
Boolean isAccountCreatedSuccessfully = accountServiceImpl.registerNewAccount(newAccount);
verify(entityManager).persist(newAccount);
verify(newAccount).setPassword(passwordEncoder.encodePassword(newAccount.getPassword(), saltSource.getSalt(newAccount)));
assertTrue(isAccountCreatedSuccessfully);
}
@Test
public void testShouldSetRoleToAccount() throws RoleNotFoundException{
Role role = new Role(); //Maybe I can use mock here?
role.setName("ROLE_REGISTERED");
when(roleDao.findRole("ROLE_REGISTERED")).thenReturn(role);
accountServiceImpl.setRoleToAccount("ROLE_REGISTERED", newAccount);
assertTrue(newAccount.getRoles().contains(role));
}
}
Câu hỏi :
- Cách tốt nhất để thực hiện các bài kiểm tra đơn vị nơi tôi có phương pháp trong các phương pháp như trong lớp dịch vụ của tôi là gì? Tôi có thể kiểm tra chúng một cách riêng biệt như trên không? [Tôi đã chia mã của mình thành một vài phương pháp để có mã sạch hơn]
- Có phải testRegisterNewAccount() kiểm tra đơn vị tốt cho phương thức dịch vụ của tôi không? Kiểm tra là màu xanh lá cây tuy nhiên tôi không chắc chắn về nó.
- Tôi nhận được lỗi trong testShouldSetRoleToAccount của mình. Tôi đang làm gì sai?
- Cách kiểm tra checkIfUsernameExists?
Có lẽ ai đó sẽ giúp tôi với điều này vì tôi đã dành một vài ngày và tôi đã không làm cho một sự tiến bộ :(
CẬP NHẬT
lớp thử nghiệm Hoàn
@RunWith(MockitoJUnitRunner.class)
public class AccountServiceImplTest extends BaseTest {
private AccountServiceImpl accountServiceImpl;
private Role role;
private Account account;
@Mock private Account newAccount;
@Mock private PasswordEncoder passwordEncoder;
@Mock private SaltSource saltSource;
@Mock private EntityManager entityManager;
@Mock private AccountDao accountDao;
@Mock private RoleDao roleDao;
@Before
public void init() {
accountServiceImpl = new AccountServiceImpl();
role = new Role();
account = new Account();
ReflectionTestUtils.setField(accountServiceImpl, "entityManager", entityManager);
ReflectionTestUtils.setField(accountServiceImpl, "passwordEncoder", passwordEncoder);
ReflectionTestUtils.setField(accountServiceImpl, "saltSource", saltSource);
ReflectionTestUtils.setField(accountServiceImpl, "accountDao", accountDao);
ReflectionTestUtils.setField(accountServiceImpl, "roleDao", roleDao);
}
@Test
public void testShouldRegisterNewAccount() {
Boolean isAccountCreatedSuccessfully = accountServiceImpl.registerNewAccount(newAccount);
verify(entityManager).persist(newAccount);
verify(newAccount).setPassword(passwordEncoder.encodePassword(newAccount.getPassword(), saltSource.getSalt(newAccount)));
assertTrue(isAccountCreatedSuccessfully);
}
@Test(expected = IllegalArgumentException.class)
public void testShouldNotRegisterNewAccount() {
doThrow(new IllegalArgumentException()).when(entityManager).persist(account);
accountServiceImpl.registerNewAccount(account);
}
@Test
public void testShouldSetRoleToAccount() throws RoleNotFoundException {
when(roleDao.findRole(anyString())).thenReturn(role);
accountServiceImpl.setRoleToAccount("ROLE_REGISTERED", account);
assertTrue(account.getRoles().contains(role));
}
@Test
public void testShouldNotSetRoleToAccount() throws RoleNotFoundException {
when(roleDao.findRole(anyString())).thenThrow(new RoleNotFoundException());
accountServiceImpl.setRoleToAccount("ROLE_RANDOM", account);
assertFalse(account.getRoles().contains(role));
}
@Test
public void testCheckIfUsernameExistsIsTrue() throws UserNotFoundException {
when(accountDao.findUsername(anyString())).thenReturn(account);
Boolean userExists = accountServiceImpl.checkIfUsernameExists(anyString());
assertTrue(userExists);
}
@Test
public void testCheckIfUsernameExistsIsFalse() throws UserNotFoundException {
when(accountDao.findUsername(anyString())).thenThrow(new UserNotFoundException());
Boolean userExists = accountServiceImpl.checkIfUsernameExists(anyString());
assertFalse(userExists);
}
@Test
public void testShouldLoadUserByUsername() throws UserNotFoundException {
when(accountDao.findUsername(anyString())).thenReturn(account);
Account foundAccount = (Account) accountServiceImpl.loadUserByUsername(anyString());
assertEquals(account, foundAccount);
}
@Test(expected = UsernameNotFoundException.class)
public void testShouldNotLoadUserByUsername() throws UserNotFoundException {
when(accountDao.findUsername(anyString())).thenThrow(new UsernameNotFoundException(null));
accountServiceImpl.loadUserByUsername(anyString());
}
}
Cảm ơn David. Trả lời câu hỏi 1 tôi hoàn toàn hiểu và tôi đã chọn tùy chọn 1. Về Câu hỏi 3 Tôi đã giải quyết được vấn đề. Tôi đã phải thay thế Tài khoản giả bằng Tài khoản được tạo bởi toán tử mới và nó là [sic!] :). Câu hỏi 4 cũng đã giúp tôi, nhưng tôi có những vấn đề khác. Như bạn có thể thấy nhờ những gợi ý của bạn, tôi đã viết các bài kiểm tra cho tất cả các phương pháp của mình. Họ làm việc ok trừ testShouldNotSetRoleToAccount và testShouldNotLoadUserByUsername. Cả hai đều thất bại khi có "expected = ...". Không có nó ok. Hơn nữa đầu tiên cũng làm cho vi lỗi và thử nghiệm là Lỗi. Bạn có thể giúp tôi? –
Rất tiếc, tôi đã mất một lúc để liên hệ lại với bạn. Nếu những kiểm tra đó thất bại với tập hợp ngoại lệ dự kiến, điều đó có nghĩa là ngoại lệ không thực sự bị ném. Bạn có chắc chắn rằng 'roleDao' và' accountDao' đã thực sự được đặt thành mocks không? Bạn có thể kiểm tra điều này với trình gỡ rối. Ngoài ra, bạn không sử dụng 'anyString()' một cách chính xác - điều này là để stubbing và xác minh, không thực sự chạy phương thức của bạn; Tôi không biết đây có phải là nguyên nhân của vấn đề của bạn hay không. Trong các dòng nơi bạn thực sự chạy các phương thức của mình, hãy đặt giá trị thực mà bạn muốn chuyển, thay vì 'anyString()'. –
Eh lol, tôi ngu ngốc. Lỗi này mà tôi đã nói về nó chỉ là thông tin bàn điều khiển từ logger. Trong roleDao khi ngoại lệ bị bắt, có logger.error (..): P. Tôi nhìn vào mã kiểm tra của tôi kỹ lưỡng và bây giờ mọi thứ đều ổn. "mong đợi" trong testShouldNotSetRoleToAccount và testCheckIfUsernameExistsIsFalse là không cần thiết. Sau đó tôi sẽ cập nhật lớp thử nghiệm của mình và chúng tôi có thể đóng cuộc thảo luận này. Cảm ơn một lần nữa David, gợi ý của bạn rất hữu ích :) –