개발 환경
- IDE: IntelliJ IDEA Ultimate
- SpringBoot 2.0.4
- Java8
- Gradle
Dependency 추가
groovy 및 spock dependency 추가
build.gradle
apply plugin: 'groovy'
dependencies {
// Spock
testCompile group: 'org.spockframework', name: 'spock-core', version: '1.1-groovy-2.4'
testCompile group: 'org.spockframework', name: 'spock-spring', version: '1.1-groovy-2.4'
// Groovy
testCompile "org.codehaus.groovy:groovy-all:2.4.15"
// Mock
testRuntime 'cglib:cglib-nodep:3.2.4'
testCompile group: 'org.objenesis', name: 'objenesis', version: '2.6'
}
Code
spock로 test code를 작성해볼 method는 getCustomerByName() 이다.
해당 method는 단순히 CustomerRepository에서 Customer entity를 가져온다.
기존에 customerRepository를 setter injection방식으로 @Autowired annotation을 붙여 사용하였는데 spock에서 mocking이 제대로 되지않아서 constructor injection방식을 사용하게 되었다.
이후에 알게되었는데 constructor injection으로 구현하였을 때, bean 생성자가 의존성 감시 기능 및 독립적으로 class를 작성할 수 있어 spring에서 권고하는 방식이라고 한다.
CustomerServiceImpl.java
@Service
public class CustomerServiceImpl implements CustomerService {
private CustomerRepository customerRepository;
@Autowired
public CustomerServiceImpl(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
@Override
public Customer getCustomerByName(String name) {
return customerRepository.findByName(name);
}
}
Spock Code
src/main/test/ 하위에 groovy 디렉토리를 생성 후, 다음과 같이 테스트 코드를 작성하였다.
실제 DB와 연동하여 test하고 싶으면 customerRepository를 Mock()으로 선언하지않고
@Autowired를 붙여주면 된다.
CustomerServiceSpec.groovy
@SpringBootTest
class CustomerServiceSpec extends Specification {
CustomerService customerService
CustomerRepository customerRepository = Mock()
// Same as @Before
def setup() {
customerService = new CustomerServiceImpl(customerRepository)
}
// Same as @After
def cleanup() {}
def "Get Customer By Name"() {
given:
def name = "John"
when:
Customer customer = customerService.getCustomerByName(name)
then:
customerRepository.findByName(name) >> Customer.builder().id(1).name(name).build()
customer.getName() == name
}
}
댓글
댓글 쓰기