test doubles, mocks, and matchers - ldstech •understanding what a test double is •creating mocks...

54
Test Doubles, Mocks, and Matchers Jeremy Lund

Upload: phamkhanh

Post on 13-Jun-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Test Doubles, Mocks, and Matchers

Jeremy Lund

Page 2: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Notes

• This is a training, NOT a presentation

• Please ask questions

• This is being recorded

• https://tech.lds.org/wiki/Java_Stack_Training

• Prerequisites

– Basic Java

– Installed LDSTech IDE (or other equivalent)

– “Unit Testing with TestNG” training

Page 3: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Agenda

• Understanding what a test double is

• Creating mocks using Mockito

• Better test expressions using Hamcrest Matchers

Page 4: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Structure of a Unit Test

Arrange Act Assert

Page 5: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Structure of a Unit Test

Arrange Given

Act When

Assert Then

Page 6: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Structure of a Unit Test

@Test

public void isValidReturnsFalseWhenNameIsEmpty() {

// Arrange / Given

Person person = new Person();

person.setName(“”);

// Act / When

person.validate();

// Assert / Then

assertFalse(person.isValid());

}

org.lds.stack.training.mocks.examples.PersonTest

Page 7: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Testing Collaborators

App Controller

Category Service

Person Service

Page 8: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Test Collaborators

@Test

public void appControllerTest() {

// Arrange / Given

CategoryService cService =

new CategoryService(categoryRepo);

PersonService pService =

new PersonService(personRepo);

AppController appController =

new AppController(cService, pService);

// Act / When

// … run the tested actions …

// Assert / Then

// … perform some assertions …

}

Page 9: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Test Collaborators

@Test

public void appControllerTest() {

// Arrange / Given

CategoryService cService =

new CategoryService(categoryRepo);

PersonService pService =

new PersonService(personRepo);

AppController appController =

new AppController(cService, pService);

// Act / When

// … run the tested actions …

// Assert / Then

// … perform some assertions …

}

Page 10: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Testing Collaborators

App Controller

Category Service

Category Repository

Person Service

Person Search Service

Person Repository

Page 11: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Testing Collaborators

App Controller

Category Service

Category Repository

Jdbc Template

Category Row Mapper

Person Service

Person Search Service

Entity Manager

Person Repository

Jdbc Template

Person Row Mapper

Page 12: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Testing Collaborators

App Controller

Category Service

Category Repository

Jdbc Template Data Source

Category Row Mapper

Person Service

Person Search Service

Entity Manager

Person Repository

Jdbc Template Data Source

Person Row Mapper

Page 13: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Testing Collaborators

App Controller

Category Service

Person Service

Page 14: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Testing Collaborators

App Controller

Category Service

Category Repository

Jdbc Template Data Source

Category Row Mapper

Person Service

Person Search Service

Entity Manager

Person Repository

Jdbc Template Data Source

Person Row Mapper

Page 15: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Testing Collaborators

App Controller

Category Service

Category Repository

Jdbc Template Data Source

Category Row Mapper

Person Service

Person Search Service

Entity Manager

Person Repository

Jdbc Template Data Source

Person Row Mapper

Page 16: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

“Gum on the Ground”

Page 17: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Test Doubles

Page 18: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Benefits of Test Doubles

• Setup

• Flexibility

• Code isolation

• Introduce deterministic behavior

• Performance

Page 19: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Types of Test Doubles

• Test stub

• Fake object

• Test spy

• Mock object

Page 20: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Which Should I Use?

• “It depends”

• Ask the question: do you need the collaborator to actually DO something with the input?

• Start with Mockito, refine if necessary

Page 21: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Enter: Mockito

• Somewhat based off of EasyMock

• Goal: cleaner mocking in tests

– High signal, low noise

• Techically a Test Spy

Page 22: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Traditional Mocking Framework Steps

Expect Run Verify

Page 23: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Mockito Mocking Steps

Expect

(if you care) Run

Verify

(if you care)

Page 24: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Adding to a Stack 3.2 Project

<dependency>

<groupId>org.mockito</groupId>

<artifactId>mockito-core</artifactId>

</dependency>

<!-- optional, but recommended -->

<dependency>

<groupId>org.hamcrest</groupId>

<artifactId>hamcrest-library</artifactId>

</dependency>

Page 25: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Adding to Other Maven Projects

<dependency>

<groupId>org.mockito</groupId>

<artifactId>mockito-core</artifactId>

<version>1.9.0</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.hamcrest</groupId>

<artifactId>hamcrest-library</artifactId>

<version>1.2.1</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.objenesis</groupId>

<artifactId>objenesis</artifactId>

<version>1.0</version>

<scope>test</scope>

</dependency>

Page 26: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Defining a Mock

import static org.mockito.Mockito.*;

ClassUnderTest obj = Mockito.mock(ClassUnderTest.class);

// More common to use static import

ClassUnderTest obj = mock(ClassUnderTest.class);

org.lds.stack.training.mocks.examples.GreeterTest

Page 27: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Mock Behavior – Expectations and Stubs

ClassUnderTest obj = mock(ClassUnderTest.class);

// By default, methods return uninitialized value

// (null, 0, 0L, false, etc.)

// Always returns 42, no matter how many times called.

when(obj.getAnswer()).thenReturn(42);

// Returns true, then false for future interactions.

when(obj.isAwesome()).thenReturn(true).thenReturn(false);

// Void methods

// (code not available for comment)

// Throwing exceptions

when(obj.getStuff()).thenThrow(new FailException());

doThrow(new OtherException()).when(obj).doStuff(); // void

Page 28: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Mock Verification

// Given

ClassUnderTest obj = mock(ClassUnderTest.class);

// When

// Actions under test

// Then

// NOTE: this verifies that it happened exactly once.

verify(obj).doStuff();

// Verifies that an action never happened

// Other modifiers:

// atLeastOnce(), times(n), atMost(n), atLeast(n)

verify(obj, never()).doStuff();

// Verifies that an action occurred at least once

verify(obj, atLeastOnce()).doStuff();

Page 29: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Argument Matchers

// Given

Translator obj = mock(Translator.class);

// When

when(obj.getGreeting(Locale.ENGLISH)).thenReturn(“Hello”);

when(obj.getGreeting(Locale.FRENCH)).thenReturn(“Bon Jour”);

// everything else returns null

when(obj.getFarewell(any(Locale.class)).thenReturn(“BRB”);

when(obj.getFarewell(Locale.ENGLISH)).thenReturn(“Goodbye”);

when(obj.getFarewell(Locale.FRENCH)).thenReturn(“Au revoir”);

Page 30: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Argument Matchers

• any(), any(Class<T>)

• any…(): anyInt(), anyString(), etc.

• any…Of(Class<T>): anyListOf(Class<T>)

• eq(Obj obj): this is the default

• matches(String regex)

• startsWith(String), endsWith(String)

• argThat(Matcher<T>)

• …That(Matcher<T>): intThat(Matcher<Integer>)

Page 31: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Lab 1

Page 32: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Argument Captors

Page 33: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Argument Captors - Syntax

Translator obj = mock(Translator.class);

// create captor

ArgumentCaptor<Locale> localeCaptor =

ArgumentCaptor.forClass(Locale.class);

// Use the captor as an argument matcher

when(obj.getGreeting(localeCaptor.capture()))

.thenReturn(“Hello”);

// … call code that uses mock …

// Get value from last call to obj.getGreeting().

Locale value = localeCaptor.getValue();

// Returns a list of all captured values, in order.

List<Locale> values = localeCaptor.getValues();

org.lds.stack.training.mocks.examples. ContactServiceTest

Page 34: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Test Spies

Page 35: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Test Spies - Syntax

Translator obj = new TranslatorImpl();

Translator spiedOn = spy(obj);

doReturn(100).when(spiedOn).getDictionarySize();

assertEquals(spiedOn.getDictionarySize(), 100);

verify(spiedOn).getDictionarySize();

org.lds.stack.training.mocks.examples.SpyTest

Page 36: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Annotations – Saving the Day Since 2004

• @Mock

• @Spy

• @Captor

• @InjectMocks

NOTE: Requires a call to MockitoAnnotations.initMocks(obj);

org.lds.stack.training.mocks.examples.InjectTest

Page 37: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Lab 2

Page 38: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Hamcrest Matchers

Page 39: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

What’s a Hamcrest Matcher?

is(equalTo(contact))

containsString(“mock”)

either(startsWith(“Test”)).or(startsWith(“Stage”))

hasPropertyWith(“address”, equalTo(“123 Fake St”))

samePropertyValuesAs(contact);

Page 40: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

What Can I Do With Them?

assertThat();

org.lds.stack.training.mocks.examples. HamcrestAssertThatTest

Page 41: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Wait! There’s More!

argThat()

org.lds.stack.training.mocks.examples. HamcrestMockitoTest

Page 42: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Mockito Limitations

• Similar to any library that needs to dynamically extend or manipulate Java classes (think Spring AOP, libraries that use CGlib, etc.)

• Can’t mock final classes

• Can’t mock static methods

• Can’t mock final methods

• Can’t mock hashcode() or equals() (why would you?)

Page 43: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

PowerMock Bends the Rules

Page 44: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

PowerMock – Mocking Static Methods

@PrepareForTest(Collections.class)

public class StaticTest {

@Test

public void testStatic() {

// Tell PowerMock to mock the static methods

PowerMockito.mockStatic(Collections.class);

// Introduce mocked behavior

Mockito.when(Collections.emptyList())

.thenReturn(Arrays.<Object>asList("1", "2"));

// Try it out!

System.out.println(Collections.emptyList());

PowerMockito.verifyStatic();

org.lds.stack.training.mocks.examples.powermock.CollectionsTest

Page 45: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

PowerMock – Mocking Finals

@PrepareForTest(FinalCountdown.class)

public class FinalTest {

@Test

public void testFinal() {

FinalCountdown finalCountdown =

PowerMockito.mock(FinalCountdown.class);

Mockito.when(finalCountdown.countdown())

.thenReturn(true, true, true, false);

Mockito.when(finalCountdown.getCurrentValue())

.thenReturn(3, 2, 1, 0);

while (finalCountdown.countdown()) {

System.out.println(

finalCountdown.getCurrentValue());

}

}

} org.lds.stack.training.mocks.examples.powermock.FinalCountdownTest

Page 46: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

PowerMock – Mocking Private Methods

@PrepareForTest(PrivatePublic.class)

public class PrivateTest {

@Test

public void testPrivate() {

PrivatePublic privatePublic =

PowerMockito.spy(new PrivatePublic("Private"));

PowerMockito.when(privatePublic,"formatTitle")

.thenReturn("Five-Star General");

System.out.println(privatePublic.getTitle());

}

}

org.lds.stack.training.mocks.examples.powermock.PrivatePublicTest

Page 47: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Tips and Tricks

Page 48: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Don’t Mock Domain Objects

Contact contact = mock(Contact.class);

when(contact.getId()).thenReturn(15L);

when(contact.getFirstName()).thenReturn(“Chuck”);

when(contact.getLastName()).thenReturn(“Testa”);

when(contact.getStreetAddress()).thenReturn(“123 Fake St”);

when(contact.getCity()).thenReturn(“Ojai”);

when(contact.getState()).thenReturn(“CA”);

// when(does.thisEverEnd()).thenReturn(“Hooray!”);

org.lds.stack.training.mocks.examples.ContactRepositoryTest

Page 49: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Inject Your Collaborators

@Service

public class SuperDuperService {

private SuperService superService;

private DuperService duperService;

@Inject

public SuperDuperService(

SuperService superService,

DuperService duperService) {

this.superService = superService;

this.duperService = duperService;

}

// provide some super-duper service!

}

org.lds.stack.training.mocks.examples.SuperDuperService

Page 50: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Provide Reasonable Defaults

@Service

public class SuperDuperService {

private SuperService superService;

private DuperService duperService =

new DefaultDuperService();

@Inject

public SuperDuperService(SuperService superService) {

this.superService = superService;

}

public void setDuperService(DuperService duperService) {

this.duperService = duperService;

}

}

org.lds.stack.training.mocks.examples.AnotherSuperDuperService

Page 51: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Consider Testing When Building

Page 52: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

What’s Next?

• Integration testing

• Test data builders

Page 53: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Creative Commons

Name Author URL

Lab icon 2 pitr http://openclipart.org/detail/22628/lab-icon-2-by-pitr/

Gum Alley Bev Sykes http://www.flickr.com/photos/basykes/713314598/

nuclear explosion tzunghaor http://openclipart.org/detail/166696/nuclear-explosion-by-tzunghaor

Reflections meddygarnet http://www.flickr.com/photos/meddygarnet/3457266724/

Caged Kids Morten Liebach http://www.flickr.com/photos/morten_liebach/4488573473/

FBI Dude elkbuntu http://openclipart.org/detail/10717/fbi-dude-by-elkbuntu

Page 54: Test Doubles, Mocks, and Matchers - LDSTech •Understanding what a test double is •Creating mocks using Mockito •Better test expressions using Hamcrest Matchers

Creative Commons

Name Author URL

365 Day 337 Collin Harvey http://www.flickr.com/photos/celloc/6913920367/

You were the chosen one!

Kyknoord http://www.flickr.com/photos/kyknoord/2092369873/

Crash Test Dummies working on Smart Car

a200/a77Wells http://www.flickr.com/photos/aiwells/4672742619/

Wolf Memory Game Evelyn Saenz http://www.flickr.com/photos/evelynsaenz/6716600387/