2. What is Unit Testing
Unit test is a method by which individual units of source code
are tested to determine if they are fit for use.
A unit is the smallest testable part of an application like
method or class.
Unit tests are written from a programmer’s perspective.
They ensures that a particular method of a class successfully
performs a set of operations.
Unit testing drives design: developer is concerned about how
client will use the interface of the class that is under the test.
3. What is not for?
It's not for testing correct inter-operation of multiple
subsystems.
NOTE: It should be a stand-alone test which is not related
to other subsystems.
It should not rely on external resources like(RDBMS,LDAP etc).
NOTE: Introducing dependencies on external resources or
data turns unit tests into integration tests.
In many cases you can't write a unit test to reproduce bug
appeared in production.
NOTE: it's not regression testing. with unit test you can
check logic responsible for interaction between different
layers.
4. The advantages of Unit Testing
● Ensure code continues to work as intended(only if it has a
good coverage)
● Safe refactoring. Allows refactoring without fear to break the
code.
● Fewer bugs. Find some tricky bugs in logic on first stage
NOTE: tricky unit test scenarios may prevent many bugs.
● Developer concentrates more on the code and design.
NOTE: less build/deploy cycles to see some progress.
green bar shows you the progress
● Documentation
5. Disadvantages of Unit testing
Big time investment. For the simple case you lose about 20%
of the actual implementation, but for complicated cases you lose
much more.
NOTE: If you correctly follow TDD it will going to save you
time later in long-term perspective!
Design Impacts. Sometimes the high-level design is not clear
at the start and evolves as you go along - this will force you to
completely redo your test which will generate a big time lose.
NOTE: postpone unit tests in this case until you have
clarified high-level design.
6. Best Practices
● Make sure your tests test one thing and one thing only.
● Readability is important for tests. (see Example)
● Each unit test should be independent from the other.
● Separate you concerns. Extract layers to improve the
design. (see Example with DAO layer)
● Mock behavior with mocks to concentrate on test
scenario.
● Test Coverage(Check coverage during testing)
● Tests should run automatically to provide continuous
feedback.
Keep the bar green to keep the code clean!
7. Bad practices
● A singleton gets implemented using a static method. Static
methods are avoided by people who do unit testing
because they cannot be mocked or stubbed.
Static methods are death to unit testability ref
● Don't rely on external resources
● Do not test the GUI.
8. JUnit - Adding new test case
Mark your test cases with @Test annotations.
Use @Before and @After to run method before and after
every test case. Several tests need similar objects created
before they can run. (See Example)
Use @BeforeClass and @AfterClass to run for one time
before and after all test cases.(Use it only to share expensive
setup)
Static imports makes code more readable: (See Example)
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
@RunWith(MockitoJUnitRunner.class)
9. JUnit test structure
Make test readable. Use next pattern:
// Given
Create some objects required for testing.
// When
Execute method that is under test
// Then
Check state and verify interaction
See example
10. JUnit - Assertion
1. Choose correct assert method from org.junit.Assert.*:
assertNull, assertNotNull, assertTrue, assertEquals...
2. Keep it simple:
assertEquals(age, calculateAge(dob)); // bad practice
assertEquals(age, 25); // Best practice. Keep it simple
3. Use overloaded method with argument for message:
assertNull("Value must be null in case of error", value);
11. JUnit - test under construction
Sometimes we need to temporarily disable a test that is
under construction. Use @Ignore annotation on method
or class to achieve it. Specify the reason why it's ignored.
@Ignore("Enable when TASK-2 is implemented")
public class MyClassTest {
@Test public void testThat1() { ... }
@Test public void testThat2() { ... }
}
public class MyClassTest {
@Ignore("Gotta go now! will fix it later.")
@Test void testThat1() { ... }
}
12. JUnit - Test Case With Exception
1. Expect that exception is thrown: (See example) @Test
(expected=EmailExistException.class) public void
testExceptionIsThrown() { ... }
2. More flexible old school way:
try { // execute method under the test customerService.add
(customer);
fail("exception must be thrown");
} catch (ServiceException exception) {
// state assertion: check error code
assertEquals(exception.getCode(), 404);
}
3. JUnit 4.7 has @Rule ExpectedException
13. State vs Interaction testing
State testing asserts properties on an object
Example: Verify that after tested method execution object has
properties: assertEquals(2, item.getCount());
Interaction testing verifies the interactions between objects.
Example: Did my controller correctly call my services in
specified order? Can be used only with mocked objects.
Mockito is a framework for interactions testing.
Mockito is a mocking framework
that tastes really good!
14. Mock behavior with mocks.
Mocks or mock objects simulate the behavior of complex, real
(non-mock) objects and are therefore useful when a real object
is impractical or impossible to incorporate into a unit test.
They provide:
● Default values unless stubbed
● Can help verify interactions, order of interaction, method
parameters etc.
Mockito is a Java based mocking framework that allows you to
write beautiful tests with clean & simple API.
15. Why Mockito is good?
● with Mockito, you only stub what you need and go on
happily completing the functionality. No need to stub
everything.
● simple and clean syntax
● all required documentation can be found in javadocs to org.
mockito.Mockito.
● Has an ability to create partial mocks.
● It tastes really good
16. JUnit - Mock in Mockito
This will mock all methods in MyService class and provide
default values:
1. @Mock MyService myService;
All classes with @Mock annotation will be injected to
@InjectMocks class by type automatically when using
@RunWith(MockitoJUnitRunner.class).
2. You can mock and inject services manually:
MyService myService = mock(MyService.class);
ServiceUnderTest service = new ServiceUnderTest();
service.setMyService(myService);
You can mock concrete classes, not only interfaces!
17. JUnit - Stubbing in Mockito
Stubbing is adding canned response to Mock object methods.
Examples:
● method stubbing:
when(mockService.someMethod(”value”))
.thenReturn(”someValue”);
● stubbing method with exception:
when(mockService.someMethod("value"))
.thenThrow(new MyException("Error"));
or stubbing void method with exception:
doThrow(new MyException(”Error”)
.when(mockService).someMethod("value");
Mockito verifies argument values in natural java style: by using
an equals() method.
18. JUnit - Argument matching in Mockito
Sometimes, when extra flexibility is required then you might
use argument matchers:
● when(mockedList.get(anyString())).thenReturn("element");
● any(ClassName.class)
● Custom argument matcher:(see ArgumentMatcher)
IMPORTANT: If you are using argument matchers, all
arguments have to be provided:
verify(mock).someMethod(anyInt(), anyString(), eq("arg"));
verify(mock).someMethod(anyInt(), anyString(), "arg") -
Wrong
19. JUnit - Verify behavior in Mockito
Once created, mock will remember all interactions. Then you
can selectively verify whatever interaction you are interested in:
● verify(mockService).someMethod("someArgs");
● verify(mockService, times(2)).someMethod("someArgs");
● verify(mockService, never()).someMethod("someArgs");
NOTE: never() is an alias to times(0)
● atLeastOnce()
● atLeast(2)
● atMost(5)
● verifyZeroInteractions(mockService)
● verifyNoMoreInteractions(mockService)
20. JUnit - Verification in order
Verification in order is flexible - you don't have to verify all
interactions one-by-one but only those that you are
interested in testing in order.
//create inOrder object passing any mocks relevent for in-order verification
InOrder inOrder = inOrder(firstMock, secondMock);
// make sure that firstMock was called before secondMock
inOrder.verify(firstMock).add("was called first");
inOrder.verify(secondMock).add("was called second");
21. JUnit - Spy(Partial mocking) in Mockito
When you use the Spy then the real methods are called (unless
a method was stubbed).
● Calls real methods unless the method is stubbed.
● Use of too much spy is potential code smell.
MyService myService = new MyService();
MyService spy = spy(myService);
//optionally, you can stub out some methods when(spy.
someMethod()).thenReturn(val);
//real method logic will be executed
spy.realMethod();
See Example
22. Test Coverage (see Example)
Eclemma plugin for eclipse: http://www.eclemma.org/
#ant coverage - to generate report from console