unit/integration testing using spock

29
Unit Testing using Spock Presented By: Anuj Aneja

Upload: anuj-aneja

Post on 14-Jan-2017

100 views

Category:

Technology


6 download

TRANSCRIPT

Page 1: Unit/Integration Testing using Spock

Unit Testing using SpockPresented By: Anuj Aneja

Page 2: Unit/Integration Testing using Spock

What is unit testing? A unit is the smallest testable part of an application like

functions, classes, procedures, interfaces. Unit testing is a method by which individual units of source code are tested to determine if they are fit for use.

Unit tests are basically written and executed by software developers to make sure that code meets its design and requirements and behaves as expected

The goal of unit testing is to segregate each part of the program and test that the individual parts are working correctly.

This means that for any function or procedure when a set of inputs are given then it should return the proper values. It should handle the failures gracefully during the course of execution when any invalid input is given.

Page 3: Unit/Integration Testing using Spock

What is unit testing?…..continued

A unit test provides a written contract that the piece of code must assure. Hence it has several benefits.

Unit testing is usually done before integration testing.

Page 4: Unit/Integration Testing using Spock

Do we need to test the code before we build it?

Page 5: Unit/Integration Testing using Spock
Page 6: Unit/Integration Testing using Spock

Advantages of Unit Testing

Issues are found at early stage. Since unit testing are carried out by developers where they test their individual code before the integration.

Unit testing helps in maintaining and changing the code. This is possible by making the codes less interdependent so that unit testing can be executed.

Unit testing helps in simplifying the debugging process. If suppose a test fails then only latest changes made in code needs to be debugged.

Page 7: Unit/Integration Testing using Spock

Unit testing using Spock

What is Spock? Why Spock? Example Test Structure Creating Mock Checking interactions with Mock object Matching invocations in mocks

Page 8: Unit/Integration Testing using Spock

Unit testing using spock

Check the order of execution Specifying a cardinality of an interaction &

wildcards Managing exceptions in tests Shared variables “>>” operator & Stubbing Good practices

Page 9: Unit/Integration Testing using Spock

What is Spock?

Spock is a unit testing framework that in great extent utilizes Groovy’s syntax making your tests comprehensible and easy on the eyes. Although it is a Groovy technology you can use it to test your Java classes as well. What is the most important is that Spock makes writing tests fun. And I really mean it.

Page 10: Unit/Integration Testing using Spock

Why Spock?

Creating a test in Spock takes less time than using its standard equivalent (combination of JUnit and some mocking framework)

Thanks to Groovy’s syntax you can improve tests clarity even further using closures and straightforward map ulization.

Page 11: Unit/Integration Testing using Spock

Example

def "should return 2 from first element of list"() { given: List<Integer> list = new ArrayList<>() when: list.add(1) then: 2 == list.get(0)}

Page 12: Unit/Integration Testing using Spock

Output: Error Message

Condition not satisfied: 2 == list.get(0)  |  |    |  |  [1]  1  false

Page 13: Unit/Integration Testing using Spock

Test Structure

Each test can be divided into three sections Given When Then

Alternative Sections: Setup expect

Page 14: Unit/Integration Testing using Spock

Mandatory Sections Example

def "should return false if user does not have role required for viewing page"() { given: // context within which you want to test the functionality. pageRequiresRole Role.ADMIN userHasRole Role.USER when: // some action is performed i.e. actual method call boolean authorized = authorizationService.isUserAuthorizedForPage(user, page) then: // expect specific result authorized == false}

Page 15: Unit/Integration Testing using Spock

Alternative Sections: setup,expect An expect block is more limited than a then block in that

it may only contain conditions and variable definitions. It is useful in situations where it is more natural to describe stimulus and expected response in a single expression. For example, compare the following two attempts to describe the Math.max() method:

when: def x = Math.max(1, 2) then: x == 2

expect: Math.max(1, 2) == 2

Page 16: Unit/Integration Testing using Spock

Flow

Page 17: Unit/Integration Testing using Spock

Creating MockIn order to create a Mock one has to call Mock() method inside a Spock test.

e.g.

def "creating example mocks"() { given: List list = Mock(List)

List list2 = Mock() // preffered way

def list3 = Mock(List) }

Page 18: Unit/Integration Testing using Spock

Checking interactions with Mock object

Now that we have created a Mock object, we can check what has happened with the object during the execution of code inside when section.

def "size method should be executed one time"() { given: List list when: list = Mock() then: 1 * list.size()}

Page 19: Unit/Integration Testing using Spock

OutputError Message:

Too few invocations for: 1 * list.size()   (0 invocations) Unmatched invocations (ordered by similarity): None

Page 20: Unit/Integration Testing using Spock

Matching invocations in mocks

def "should fail due to wrong user"() { given: UserService userService = Mock() User user = new User(name: 'Mefisto') when: userService.save(user) then: 1 * userService.save({ User u -> u.name == 'Lucas' })}

Too few invocations for:

1 * userService.save({ User u -> u.name == 'Lucas' }) (0 invocations)

Page 21: Unit/Integration Testing using Spock

Check the order of executionWhat is more you can even specify the order by which interactions should take place. This is achieved by creating numerous thensections.

def "should first save object before committing transaction"() { given: UserService service = Mock() Transaction transaction = Mock() when: service.save(new User()) transaction.commit() then: 1 * service.save(_ as User) then: 1 * transaction.commit()}

Page 22: Unit/Integration Testing using Spock

Specifying a cardinality of an interaction & wildcards

then:    // should not be invoked at all    0 * list.size()     // should be invoked at least one time    (1.._) * list.size()     // should be invoked at most one time    (_..1) * list.size()     // any number of calls    _ * list.size()

Page 23: Unit/Integration Testing using Spock

Managing exceptions in testsThere are special method for handling exception checkingThrown(), notThrown(), noExceptionThrown()

e.g.

def "should throw IllegalArgumentException with proper message"() { when: throw new IllegalArgumentException("Does description matter?") then: def e = thrown(IllegalArgumentException) e.message == "Does description matter?"}

Page 24: Unit/Integration Testing using Spock

Shared variablesIf for some reason you would prefer to share the state of objects created at the level class you can annotate this particular variable with @Shared annotation.

@Sharedprivate List<Integer> list = []

def "test 1"() { when: list.add(1) then: list.size() == 1}

def "test 2"() { when: list.add(1) then: list.size() == 2}

Page 25: Unit/Integration Testing using Spock

“>>” operator & stubbingStubbing is the act of making collaborators respond to method calls in a certain way. When stubbing a method, you don’t care if and how many times the method is going to be called; you just want it to return some value, or perform some side effect, whenever it gets called.

For Example:

interface Subscriber { String receive(String message)}

Now, let’s make the receive method return "ok" on every invocation:

subscriber.receive(_) >> "ok"

Page 26: Unit/Integration Testing using Spock

"Whenever the subscriber receives a message, make it respond with 'ok'."

Compared to a mocked interaction, a stubbed interaction has no cardinality on the left end, but adds a response generator on the right end:

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

Page 27: Unit/Integration Testing using Spock

Good practicies:

Using descriptive methods inside test Removing disruptive code

Page 28: Unit/Integration Testing using Spock

Removing disruptive codeprivate User userprivate Action actionprivate TicketOrder order

private BookingService objectUnderTest = new BookingService()

def "should throw exception if user tries to cancel tickets to a gig that starts in less than two days"() { given: userHasRoleUser() cancelActionOn10thOfDec2000() showIsGigThatStartsOn11thOfDec2000() when: objectUnderTest.book(user, order, action) then: thrown(IllegalActionException)}

Page 29: Unit/Integration Testing using Spock

Q & A