def “user service can create user”() { given: def user = UserMother.johnny().build() def userForm = new UserForm(user.name, …) when: def result = underTest.createUser(userForm)
}
then: 1 * otherService.isNameOK(_ as UserForm) >> true 1 * userRepository.persist(_ as User) >> user 0 * userRepository._ result == user
Slide 23
def “user service can create user”() { given: def user = UserMother.johnny().build() def userForm = new UserForm(user.name, …) // name matches rules otherService.isNameOK() >> true // user is persisted userRepository.persist() >> user when: def result = underTest.createUser(userForm)
}
then: 0 * userRepository._ result == user
Slide 24
Anti-pattern #4: Ineffective tests
Slide 25
@PostMapping @ResponseBody public UserDto create(@RequestBody @Valid UserForm form){ User user = userService.create(form); return userConverter.convert(user); }
Slide 26
def “controller calls the service and converter”() { given: def user = UserMother.johnny().build() def userForm = new UserForm(user.name, …) userService.create() >> user userConverter.convert() >> … when: def result = underTest.create(form)
then: result.name == user.name result.address == user.address }
Slide 27
Don’t write unit tests! Do write integration tests!
Slide 28
A refresher
Slide 29
def “user is created, updated and deactivated”() { given: def user = UserMother.johnny().build()
when: def createdUserDto = /* trigger create REST API */ then: createdUserDto.name == user.name userRepository.findByName(user.name) != null …
Don’t write integration tests! Do write unit tests!
Slide 33
@Unroll def “update changes status from #currentStatus to #newStatus”() { given: def user = new User(status: currentStatus) when: user.updateStatus(newStatus)
then: user.status == newStatus where: currentStatus
| newStatus
UserStatus.Inactive
| UserStatus.Active
UserStatus.Inactive
| UserStatus.Deleted
… }
Slide 34
Summary Avoid mock overuse Don’t Repeat Yourself
Test contracts, not implementations Don’t test for the sake of testing Distribute tests across the test pyramid
Slide 35
To me, legacy code is simply code… without tests Michael Feathers Working Effectively With Legacy Code