===== JUnit with Mockito ===== ^What^ Where^ |Fast Introduction into Assertions| [[http://www.vogella.com/articles/JUnit/article.html#usingjunit_asserts|vogella.com]] | |Introduction into unit testing| [[http://tutorials.jenkov.com/java-unit-testing/index.html|tutorials.jenkov.com]] | |Mockito documentation | [[http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html|docs.mockito.googlecode.com/]]| |Comparisson: Mocks and Stubs | [[http://martinfowler.com/articles/mocksArentStubs.html|http://martinfowler.com/articles/mocksArentStubs.html]] | ==== Fallpits ==== ^ Fallpit^ Descr^ | Async. Tests| When doing jobs on the UI thread inside a test - look out, that the test do not return, before the async UI job gets a chance to be done. @Test public void test() { ... UI call ... //let the UI Thread wait 1000 ms, before returning long stopTimestampt = System.currentTimeMillis() + 1000; while (System.currentTimeMillis() < stopTimestampt) { Display.getDefault().readAndDispatch(); } } | ==== JUnit ==== ==== Mockito ==== == Glossar == ^What^ Where^ |Mock|imitate an Object, with all methods. On default mock-methods return null, false...| |Stub|getting Mock's methods return something else, than default values.| |Spy|spy at object, replace some original methods.| == Basics == public class MyTest { //1. FILL THE CONTEXT //@Spy annotated fields are in context of Mockito and can be injected by @InjectMocks @Spy private PreferenceService service = new LocalPreferenceService(); //@Mock annotated fields are in context of Mockito and can be injected by @InjectMocks @Mock(name = "service2") private PreferenceService service2; /** * This is important not to put multiple Objects of same type into the context by @Spy and @Mock, or there will be an ambigous situation and none of them will be injected by Mockito. */ //2. TELL THE MOCKITO TO FILL THE @Inject ANNOTATED FIELDS INSIDE OF preferenceStoreDb BY @Spy AND @Mock ANNOTATED FIELDS FROM THIS TEST @InjectMocks private RemotePreferenceStore preferenceStoreDb = new RemotePreferenceStore(); //3. INIT THE @Mock @Spy ANNOTATED OBJECTS, INJECT THEM INTO @InjectMocks ANNOTATED OBJECTS @Before public void initMocks() { MockitoAnnotations.initMocks(this); } @Test public void getDefaultDefaultTest() { ... } } == Stub methods == The methods for mocked objects - can be forced to return some stuff. /* Mock the preference lookup. It's methods will be empty and must be stubed. */ @Mock PreferenceLookup preferenceLookup; @Before public void initMocks() { MockitoAnnotations.initMocks(this); // stub methods, so that they return an empty list List> showNotificationPreferences = new ArrayList<>(); Mockito.when(preferenceLookup.getValue(Mockito.any(ViewablePreference.class))).thenReturn( showNotificationPreferences); Mockito.when(preferenceLookup.getValue(Mockito.anyString())).thenReturn(showNotificationPreferences); preferenceLookup.getValue(new ViewablePreference()); // return showNotificationPreferences now preferenceLookup.getValue("test"); // return showNotificationPreferences now == Test E4 Plugins == The biggest problem in testing e4 stuff - is in faking the e4 platform classes. The usual approach is to create an **IEclipseContext**, fill it with mocks, inject the context into classes under test. /* Create an Eclipse Context */ IEclipseContext eclipseContext = EclipseContextFactory.create(); /* Mock the preference lookup. It's methods will be empty and must be stubed. */ @Mock PreferenceLookup preferenceLookup; /* classes under test */ MixedMessaging mixedMessaging; NotificationFactory notificationFactory; @Before public void initMocks() { /* create all the Spy and Mock annotated objects */ MockitoAnnotations.initMocks(this); /* stub methods, so that they return an empty list */ List> showNotificationPreferences = new ArrayList<>(); Mockito.when(preferenceLookup.getValue(Mockito.any(ViewablePreference.class))).thenReturn( showNotificationPreferences); Mockito.when(preferenceLookup.getValue(Mockito.anyString())).thenReturn(showNotificationPreferences); preferenceLookup.getValue("test"); // return showNotificationPreferences now /* add mocks to the Context */ eclipseContext.set(PreferenceLookup.class, preferenceLookup); /* class under test 1 */ eclipseContext.set(MixedMessaging.class, mixedMessaging); // class under test 2 NotificationServiceCreationFunction notificationServiceCreationFunction = new NotificationServiceCreationFunction(); notificationFactory = notificationServiceCreationFunction.compute(eclipseContext); } @Test public void test() { //test here }