I want to compare (assert equals) for training purposes two lists in stream. So every id from sampleUsers() with every id from body of response entity should be compared. Should I create another stream? If yes then how to use it?
@Test
void findAllUsers() {
when(userService.findAll()).thenReturn(sampleUsers());
ResponseEntity<List<UserDto>> responseEntity = userController.findAll();
//first assert
assertEquals(responseEntity.getStatusCode().value(), 200);
//second assert
assertEquals(responseEntity.getBody().size(), sampleUsers().size());
//third assert
responseEntity.getBody().stream()
.filter(user -> user.getId() != null)
.filter(user -> user.getUsername() != null)
//TODO check for each user if:
// user.getId is equal to id from sampleUsers() list
// something like: assert equals user.getId(), sampleUsers.get(0).getId()
}
CodePudding user response:
One way is to assert each element of the stream separately which can be done with the help of following code. You can write a function for asserting streams.
static void assertStreamEquals(Stream<User> s1, Stream<User> s2) {
Iterator<Student> iter1 = s1.iterator(), iter2 = s2.iterator();
while(iter1.hasNext() && iter2.hasNext())
assertEquals(iter1.next().id, iter2.next().id);
assert !iter1.hasNext() && !iter2.hasNext();
}
and call it by passing your two streams.
@Test
void findAllUsers() {
when(userService.findAll()).thenReturn(sampleUsers());
ResponseEntity<List<UserDto>> responseEntity = userController.findAll();
//first assert
assertEquals(responseEntity.getStatusCode().value(), 200);
//second assert
assertEquals(responseEntity.getBody().size(), sampleUsers().size());
//third assert
assertStreamEquals(responseEntity.getBody(),sampleUsers);
(Assuming User is the class name for users)
CodePudding user response:
There are many ways to do that assertion. You could override equals() in UserDto class.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || this.getClass() != o.getClass()) return false;
UserDto userDto = (UserDto) o;
return this.id.equals(userDto.id);
}
And a implement a Comparator for UserDto class. This is going to be used to sort both lists.
public class UserDtoComparatorById implements Comparator<UserDto> {
@Override
public int compare(UserDto o1, UserDto o2) {
return o1.getId().compareTo(o2.getId());
}
}
Finally.
@Test
void findAllUsers() {
when(userService.findAll()).thenReturn(sampleUsers());
ResponseEntity<List<UserDto>> responseEntity = userController.findAll();
//first assert
assertEquals(responseEntity.getStatusCode().value(), 200);
//second assert (this is optional)
assertEquals(responseEntity.getBody().size(), sampleUsers().size());
// to prevent false negatives, in case both lists have same objects
// but different orders
Comparator<UserDto> comparator = new UserDtoComparatorById();
sampleUsers.sort(comparator);
responseEntity.getBody().sort(comparator);
//third assert
assertEquals(responseEntity.getBody(), sampleUsers);
//same assertion but using streams
AtomicInteger i = new AtomicInteger(0);
assertEquals(
list1.stream()
.filter(user -> user.equals(list2.get(i.getAndIncrement())))
// or: filter(user -> user.getId().equals(list2.get(i.getAndIncrement()).getId()))
.count(),
list1.size()
);
}
The third assert will work because both lists are sorted and assertEquals() will invoke UserDto.equals() for each element in the same position. As UserDto.equals() is overriten to check only UserDto.id, it will check the id instead of the Object pointer (address in memory), therefore returning true.
Note that in the second alternative you can not use int i because variables inside lambda functions need to be final. A simple workaround is using AtomicInteger.
