Groovy Testing
16 March 2016
My previous post is all about writing a simple Groovy CRUD application. It includes writing your views in Groovy as well though it doesn't involve where to put the files. But if you're a seasoned Java developer, you should know your way out.
What it lacks is how to test your Groovy classes which I'm about to document on this post.
FakeLoader
This is a workaround assuming your Spring Boot application bootstraps more @Configuration
and you don't want to include them in your integration tests.
import org.junit.Test
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.test.context.ActiveProfiles
/**
* For integration tests
*/
@ActiveProfiles("dev")
@SpringBootApplication
class FakeLoader {
}
Repository integration test
package com.manalo.repository
import com.manalo.FakeLoader
import com.manalo.config.HttpSessionConfig
import com.manalo.domain.User
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.SpringApplicationConfiguration
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.web.WebAppConfiguration
import spock.lang.Specification
@ActiveProfiles("dev")
@SpringApplicationConfiguration(classes = FakeLoader)
@WebAppConfiguration
class UserRepositorySpec extends Specification{
@Autowired
UserRepository userRepository
User user
def setup() {
user = new User(id: 1, username: "admin", password: "secret")
}
def "Should save user"() {
when: "save is invoked"
userRepository.save(user)
then: "user saved and searchable"
User actual = userRepository.findOne(1)
actual.getId() == 1
actual.getUsername() == "admin"
actual.getPassword() == "secret"
}
def "Should edit user"() {
String username = "updated user"
String password = "updated password"
when: "update is invoked"
user.setUsername(username)
user.setPassword(password)
userRepository.save(user)
then: "user updated and searchable"
User actual = userRepository.findOne(1)
actual.getId() == 1
actual.getUsername() == username
actual.getPassword() == password
}
def "Should delete user"() {
when: "user is invoked"
userRepository.delete(user)
then: "user deleted and not searchable"
User actual = userRepository.findOne(1)
assert actual == null
}
}
Service layer test
package com.manalo.controller
import com.manalo.domain.User
import com.manalo.repository.UserRepository
import com.manalo.service.UserService
import spock.lang.Specification
class UserServiceSpec extends Specification {
UserService userService
UserRepository userRepository = Mock(UserRepository)
final Integer userId = 1
def setup() {
userService = new UserService(userRepository: userRepository)
}
def "Should find all users"() {
when: "the users are retrieved"
userService.list()
then: "a list of users is returned"
1 * userRepository.findAll()
}
def "Should find by id"() {
when: "looking for user.id $userId"
userService.findById(userId)
then: "user.id $userId is found"
1 * userRepository.findOne(userId)
}
def "Should save a user"() {
given: "a new user"
User user = new User()
when: "save is invoked"
userService.save(user)
then: "user is saved"
1 * userRepository.save(user)
}
def "Should update existing user"() {
given: "an existing user"
User user = new User()
user.id = userId
userRepository.findOne(userId) >> user
when: "save is invoked"
userService.save(user)
then: "user is saved"
1 * userRepository.save(user)
}
def "Should delete existing user"() {
given: "an existing user"
User user = new User()
user.id = userId
userRepository.findOne(userId) >> user
when: "delete is invoked"
userService.delete(user)
then: "user is deleted"
1 * userRepository.delete(user)
}
}
Controller test
package com.manalo.controller
import com.manalo.domain.User
import com.manalo.service.UserService
import org.springframework.test.web.servlet.MockMvc
import spock.lang.Specification
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*
class UserControllerSpec extends Specification {
MockMvc mockMvc
UserService userService = Mock(UserService)
def setup() {
def controller = new UserController(userService: userService)
mockMvc = standaloneSetup(controller).build()
}
def "should return list of users"() {
given:
final String userList = "/user/list"
when:
"requesting $userList"
def response = mockMvc.perform(get(userList))
then: "receive 200"
response.andExpect(status().isOk())
1 * userService.list()
}
def "should load screen for adding new user"() {
given:
final String userAdd = "/user/add"
when:
"requesting $userAdd"
def response = mockMvc.perform((get(userAdd)))
then: "receive 200"
response.andExpect(status().isOk())
.andExpect(view().name("views/user/edit"))
}
def "should load screen for editing user"() {
given:
final String userEdit = "/user/1"
when:
"requesting $userEdit"
def response = mockMvc.perform((get(userEdit)))
then: "receive 200"
response.andExpect(status().isOk())
.andExpect(view().name("views/user/edit"))
1 * userService.findById(1)
}
def "should redirect after save"() {
given:
final String userSave = "/user/save"
when:
"requesting $userSave"
def response = mockMvc.perform((post(userSave)))
then: "receive 302"
response.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/user/list"))
}
def "should delete existing user"() {
given:
final String userDelete = "/user/delete"
when:
"requesting $userDelete"
def response = mockMvc.perform(post(userDelete))
then: "receive 302"
response.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/user/list"))
}
}