Programing/Java

Spock Framework을 이용한 Unit test 작성

BUST 2018. 6. 25. 22:42

Spock Framework을 이용한 Unit test 작성

Java Application을 개발하면서 Unit Test를 작성을 할때 jUnit과 Mockito를 이용하여 작성을 할수도 있지만 테스트 코드만 다른 코드로 간다면 좀더 쉽게 Unit Test를 작성을 할수 있다. 그 중에 Groovy를 언어를 이용한 Test 코드 작성에 대해 알아보자.


Reference

- http://spockframework.org/spock/docs/1.1/index.html


gradle

apply plugin: "groovy"

....

compile "org.codehaus.groovy:groovy-all:2.4.15"
testCompile "org.spockframework:spock-core:1.1-groovy-2.4"

- 기본적으로 Groovy를 언어를 사용하기 때문에 plugin과 groovy dependency를 추가를 한다.


specfication

class MyFirstSpecification extends Specification {
  // fields
def obj = new ClassUnderSpecification()
def coll = new Collaborator()
  // fixture methods
  // feature methods
  // helper methods
}

fixture method

def setup() {}          // run before every feature method
def cleanup() {}        // run after every feature method
def setupSpec() {}     // run before the first feature method
def cleanupSpec() {}   // run after the last feature method
- 이미 고정이 되어있는 매서드, test class를 시작될때나 등의 cycle에 대해 매서드 이름을 통해 실행시킬수가 있다.

feature methd

def "pushing an element on the stack"() {
  // blocks go here
}

- method에 문장 형식의 이름을 넣을수가 있다.

block

Blocks2Phases

when/then

when:
stack.push(elem)

then:
!stack.empty
stack.size() == 1
stack.peek() == elem

- when : 실제 코드를 테스트 하는 부분

- then : 테스트 이후 검증


setup/when/then

def "HashMap accepts null key"() {

  setup:

  def map = new HashMap()


  when:

  map.put(null, "elem")


  then:

  notThrown(NullPointerException)

}


where

def "computing the maximum of two numbers"() {
  expect:
  Math.max(a, b) == c

  where:
  a << [5, 3]
  b << [1, 9]
  c << [5, 9]
}

- where 를 이용하여 데이터의 조합을 넣을수가 있다.


with

def "offered PC matches preferred configuration"() {
  when:
  def pc = shop.buyPc()

  then:
  with(pc) {
    vendor == "Sunny"
    clockRate >= 2333
    ram >= 406
    os == "Linux"
  }
}


documenation

setup: "open a database connection"
// code goes here

and: "seed the customer table"
// code goes here

and: "seed the product table"
// code goes here


Mocking object

def subscriber = Mock(Subscriber)
def subscriber2 = Mock(Subscriber)

subscriber.receive(_) >> "ok"
|          |       |     |
|          |       |     response generator
|          |       argument constraint
|          method constraint
target constraint

- Mock 을 이용하여 mock object를 생성을 할수가 있다.

- >>를 이용하여 mock object에 해당하는 매서드의 리턴값을 mocking 할수가 있다.



Argument Constraints

1 * subscriber.receive("hello")     // an argument that is equal to the String "hello"
1 * subscriber.receive(!"hello")    // an argument that is unequal to the String "hello"
1 * subscriber.receive()            // the empty argument list (would never match in our example)
1 * subscriber.receive(_)           // any single argument (including null)
1 * subscriber.receive(*_)          // any argument list (including the empty argument list)
1 * subscriber.receive(!null)       // any non-null argument
1 * subscriber.receive(_ as String) // any non-null argument that is-a String
1 * subscriber.receive({ it.size() > 3 }) // an argument that satisfies the given predicate
                                          // (here: message length is greater than 3)


Sequence of returns

subscriber.receive(_) >>> ["ok", "error", "error", "ok"]
- where 문과 동일

Computing Return Values

subscriber.receive(_) >> { args -> args[0].size() > 3 ? "ok" : "fail" }


subscriber.receive(_) >>> ["ok", "fail", "ok"] >> { throw new InternalError() } >> "ok"