JUnit & Mockito, first steps

renatoprimavera 8,947 views 57 slides Jul 20, 2014
Slide 1
Slide 1 of 57
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57

About This Presentation

JUnit & Mockito, first steps


Slide Content

JUnit & Mockito,
First steps


@QuadraticBE

Jul. 2014

Let’s start with
JUnit

JUnit is a
programmer-oriented
testing framework for Java
It is a simple framework to write
repeatable tests

JUnit is linked as a JAR at
compile-time
The framework resides under package
org.junit for JUnit 4 and later

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>

...
</dependencies>



in the
POM
It’s really simple to integrate JUnit
in your Maven Project

If not using Maven,
all you need is to add 2 JARs
on your test classpath
- junit.jar
- hamcrest-core.jar

JUnit is based on
Java annotations

@org.junit.Test
@org.junit.BeforeClass
@org.junit.Before
@org.junit.AfterClass
@org.junit.After

import org.junit.*;

public class TestFoobar {

}



Let’s start a JUnit Test Case

@BeforeClass
public static void setUpClass() throws Exception {
// Code executed before the first test method
}

@Before
public void setUp() throws Exception {
// Code executed before each test
}




It’s possible to define some test context
(called “Test Fixture”), before (“setUp”)...

@AfterClass
public static void tearDownClass() throws Exception {
// Code executed after the last test method
}

@After
public void tearDown() throws Exception {
// Code executed after each test
}







...and after (“tearDown”)...

@Test
public void testOneThing() {
// Code that tests one thing
}

@Test
public void testAnotherThing() {
// Code that tests another thing
}








Now you’re ready to write tests themselves

> Assertions
(and Matchers…)

JUnit provides assertion methods for all
primitive types and Objects and arrays
The parameter order is “expected value”
followed by “actual value”

Optionally the first parameter can be a String
message that is output on failure

import static org.junit. Assert.*;

assertEquals("failure - strings not equal", "text", "text");
assertFalse("failure - should be false", false);
assertSame("should be same", aNumber, aNumber);
assertArrayEquals("failure - byte arrays not same", expected,
actual);

There is a slightly different
assertion, “assertThat” that
takes a Matcher object

import static org.junit.Assert.*;
import static org.junit.matchers. JUnitMatchers.*;

assertThat("albumen", both(containsString("a")).and
(containsString("b")));
assertThat(Arrays.asList("one", "two", "three"), hasItems
("one", "three"));
assertThat(Arrays.asList(new String[] { "fun", "ban", "net"
}), everyItem(containsString("n")));

Note that expected and actual
are reversed compared to the
other assert methods...

assertThat can also be used with
Hamcrest Matchers


Hamcrest Provides a library of matcher objects (also
known as constraints or predicates) allowing 'match'
rules to be defined declaratively, to be used in other
frameworks

Hamcrest it is not a testing library: it just happens that
matchers are very useful for testing

import static org.junit.Assert.*;
import static org.hamcrest. CoreMatchers.*;

assertThat("good", allOf(equalTo("good"), startsWith
("good")));
assertThat("good", anyOf(equalTo("bad"), equalTo("good")));
assertThat(7, not(CombinableMatcher.<Integer> either (equalTo
(3)).or(equalTo(4))));
assertThat(new Object(), not(sameInstance(new Object())));

> Test Suites
(how to aggregate tests)

Using Suite as a runner
allows you to manually build
a suite containing tests from
many classes

To use it, annotate a class with
@RunWith(Suite.class) and
@SuiteClasses(TestClass1.class, ...)

When you run this class, it will run all
the tests in all the suite classes

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
TestFeatureLogin.class, TestFeatureLogout.class,
TestFeatureNavigate.class, TestFeatureUpdate.class
})

public class FeatureTestSuite {
// the class remains empty,
// used only as a holder for the above annotations
}

> Miscellaneous

Use JUnitCore to run tests and see
the results on the console


> java org.junit.runner.JUnitCore TestClass1 [...other
test classes...]





Both your test class and junit must be on the classpath

If using Maven, just execute

> mvn test





...and the Surefire plugin of Maven
will execute all JUnit tests under
src/test/java

The tests execution report
is then available in
target/surefire-reports

<?xml version="1.0" encoding="UTF-8" ?>
<testsuite failures="0" time="0.015" errors="0" skipped="0" tests="1"
name="com.mycompany.app.AppTest">
<properties>
...
</properties>
<testcase time="0.002" classname="com.mycompany.app.AppTest" name="
testApp"/>
</testsuite>

If for some reason, you don't
want a test to fail, you just want
it ignored, you temporarily
disable a test

@Ignore("Test is ignored as a demonstration")
@Test
public void testSane() {
assertThat(1, is(1));
}

Tests that 'runaway' or
take too long, can be
automatically failed

There are two options for
implementing timeout

Timeout parameter on @Test
Annotation (applies to test method)

@Test(timeout=1000)
public void testWithTimeout() {
...
}

#1

Timeout Rule (applies to entire test
class)

public class HasGlobalTimeout {

@Rule
public Timeout globalTimeout = new Timeout(10000);
// 10 seconds max per method tested

@Test
public void testInfiniteLoop{

}
}




#2

OK for JUnit
Let’s see


now...

Mockito is a Java framework
allowing the creation of
test double objects
(mock objects) in automated
unit tests

Test Double is a generic term for any
case where you replace a production
object for testing
purposes

Dummy objects are passed around but never actually
used. Usually they are just used to fill parameter lists

Fake objects actually have working implementations, but
usually take some shortcut which makes them not suitable
for production (an InMemoryTestDatabase is a good
example)
There are various kinds of double

Stubs provide canned answers to calls made during the
test, usually not responding at all to anything outside
what's programmed in for the test

Spies are stubs that also record some information based
on how they were called. One form of this might be an
email service that records how many messages it was sent

Mocks are pre-programmed with expectations which form
a specification of the calls they are expected to receive.
They can throw an exception if they receive a call they
don't expect and are checked during verification to ensure
they got all the calls they were expecting.

Why mocking?
Some “real” objects required in Unit tests are
really complex to instanciate and/or configure

Sometimes, only interfaces exist,
implementations are not even coded

<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>

...
</dependencies>



in the
POM
It’s really simple to integrate
Mockito in your Maven Project

Now we can verify interactions
through mock objects

//Let's import Mockito statically so that the code looks clearer
import static org.mockito.Mockito.*;

//mock creation
List mockedList = mock(List.class);

//using mock object
mockedList.add("one");
mockedList.clear();

//verification
verify(mockedList).add("one");
verify(mockedList).clear();

Once created, mock will
remember all interactions

Then you can selectively verify
whatever interaction you are
interested in

By default, for all methods
that return value, mock returns null,
an empty collection or appropriate
primitive/primitive wrapper value
(e.g: 0, false, ...)

But wait!

This is where stubbing comes
//You can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);

//stubbing
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException());

//following prints "first"
System.out.println(mockedList.get(0));

//following throws runtime exception
System.out.println(mockedList.get(1));

//following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));

Mockito verifies argument values in natural
java style: by using an equals() method

Sometimes, when extra flexibility is
required then you might use
argument matchers

//stubbing using built-in anyInt() argument matcher
when(mockedList.get(anyInt())).thenReturn("element");


//stubbing using hamcrest (let's say isValid()
//returns your own hamcrest matcher):
when(mockedList.contains( argThat(isValid()))).thenReturn("element");


//you can also verify using an argument matcher
verify(mockedList).get( anyInt());


Here are some argument matchers

verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));
//above is correct - eq() is also an argument matcher


verify(mock).someMethod(anyInt(), anyString(), "third argument");
//above is incorrect - exception will be thrown because third argument is
//given without an argument matcher

Note that if you are using argument matchers,
all arguments have to be provided by matchers

Verifying exact number of invocations
/ at least x / never
//exact number of invocations verification
verify(mockedList, times(2)).add("twice");
verify(mockedList, times(3)).add("three times");

//verification using never(). never() is an alias to times(0)
verify(mockedList, never()).add("never happened");

//verification using atLeast()/atMost()
verify(mockedList, atLeastOnce()).add("three times");
verify(mockedList, atLeast(2)).add("five times");
verify(mockedList, atMost(5)).add("three times");

Verification in order
Single mock whose methods must be invoked in
a particular order


List singleMock = mock(List.class);

//using a single mock
singleMock.add("was added first");
singleMock.add("was added second");

//create an inOrder verifier for a single mock
InOrder inOrder = inOrder(singleMock);

//following will make sure that add is first called with "was added first,
//then with "was added second"
inOrder.verify(singleMock).add("was added first");
inOrder.verify(singleMock).add("was added second");

Verification in order
Multiple mocks that must be used in a particular order


List firstMock = mock(List.class);
List secondMock = mock(List.class);

//using mocks
firstMock.add("was called first");
secondMock.add("was called second");

//create inOrder object passing any mocks that need to be verified in order
InOrder inOrder = inOrder(firstMock, secondMock);

//following will make sure that firstMock was called before secondMock
inOrder.verify(firstMock).add("was called first");
inOrder.verify(secondMock).add("was called second");

Sometimes we need to stub with
different return value/exception
for the same method call, we need
to stub consecutive calls (iterator-
style stubbing)

when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");

//First call: throws runtime exception:
mock.someMethod("some arg");

//Second call: prints "foo"
System.out.println(mock.someMethod("some arg"));

//Any consecutive call: prints "foo" as well (last stubbing wins).
System.out.println(mock.someMethod("some arg"));

Alternative, shorter version of consecutive stubbing
when(mock.someMethod("some arg"))
.thenReturn("one", "two", "three") ;

It’s also possible to create
spies of real objects

When you use the spy then
the real methods are called
(unless a method was
stubbed)

List list = new LinkedList();
List spy = spy(list);

//optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);

//using the spy calls *real* methods
spy.add("one");
spy.add("two");

//prints "one" - the first element of a list
System.out.println(spy.get(0));

//size() method was stubbed - 100 is printed
System.out.println(spy.size());

//optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");

So if you keep the real instance and interact with it, don't
expect the spied to be aware of those interaction and their
effect on real instance state

The corollary is that when an unstubbed method is called on
the spy but not on the real instance, you won't see any
effects on the real instance

To know when spying real objects!
Mockito does not delegate calls to the passed real
instance, instead it actually creates a copy of it

Capturing arguments for further assertions
with ArgumentCaptor
//create the ArgumentCaptor for class Person
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);

//verify that the doSomething method of the mock object was called
//with a Person argument
verify(mock).doSomething( argument.capture());

//assert that the name of that Person argument was “John”
Person person = argument.getValue();
assertEquals("John", person.getName());

Sources

http://junit.org/
http://en.wikipedia.org/wiki/JUnit
http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html
https://code.google.com/p/mockito/
http://en.wikipedia.org/wiki/Mockito
http://www.martinfowler.com/bliki/TestDouble.html

Thanks

Renato Primavera
Quadratic Founder
www.quadratic.be
[email protected]