26
Unit testing (basic) November 2011

Unit testing basic

Embed Size (px)

Citation preview

Page 1: Unit testing basic

Unit testing

(basic)November 2011

Page 2: Unit testing basic

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.

Page 3: Unit testing basic

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.

Page 4: Unit testing basic

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 stageNOTE: 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

Page 5: Unit testing basic

Disadvantages of Unit testingBig 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.

Page 6: Unit testing basic

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!

Page 7: Unit testing basic

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.

Page 8: Unit testing basic

JUnit - Adding new test caseMark 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)

Page 9: Unit testing basic

JUnit test structure

Make test readable. Use next pattern:

// GivenCreate some objects required for testing.

// WhenExecute method that is under test

// ThenCheck state and verify interaction

See example

Page 10: Unit testing basic

JUnit - Assertion

1. Choose correct assert method from org.junit.Assert.*:assertNull, assertNotNull, assertTrue, assertEquals...

2. Keep it simple:assertEquals(age, calculateAge(dob)); // bad practiceassertEquals(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);

Page 11: Unit testing basic

JUnit - test under construction

@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() { ... } }

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.

Page 12: Unit testing basic

JUnit - Test Case With Exception1. 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 codeassertEquals(exception.getCode(), 404);}3. JUnit 4.7 has @Rule ExpectedException

Page 13: Unit testing basic

State vs Interaction testingState testing asserts properties on an objectExample: 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 frameworkthat tastes really good!

Page 14: Unit testing basic

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.

Page 15: Unit testing basic

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

Page 16: Unit testing basic

JUnit - Mock in MockitoThis 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!

Page 17: Unit testing basic

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.

Page 18: Unit testing basic

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

Page 19: Unit testing basic

JUnit - Verify behavior in MockitoOnce 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)

Page 20: Unit testing basic

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 verificationInOrder inOrder = inOrder(firstMock, secondMock); // make sure that firstMock was called before secondMockinOrder.verify(firstMock).add("was called first");inOrder.verify(secondMock).add("was called second");

Page 21: Unit testing basic

JUnit - Spy(Partial mocking) in MockitoWhen 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

Page 22: Unit testing basic

Test Coverage (see Example)Eclemma plugin for eclipse: http://www.eclemma.org/

#ant coverage - to generate report from console

Page 23: Unit testing basic

Test Driven Development

After that build project, deploy, make sure that it works. See Example

Page 24: Unit testing basic

Unit testing is a lot like going to the gym

Page 25: Unit testing basic

No pain, no gain

*

Page 26: Unit testing basic

Let's drink!

Contact InformationEmail: [email protected]