From ea85a9e9f5524be8f8831b5a02939037fd3762a2 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:25:27 +0000 Subject: [PATCH 1/4] Support testing against interfaces instead of implementations - Enhanced CorrespondingTypeSearcher to look for tests of supertypes and implementations. - Included concrete implementations in the results when an interface/abstract class is matched. - Excluded 'pure' interfaces/abstract classes from results when concrete implementations are found, unless they have default methods or non-abstract methods. - Added comprehensive tests in InterfaceCorrespondingTypeSearcherTest. Closes #205 Co-authored-by: RoiSoleil <3462260+RoiSoleil@users.noreply.github.com> --- .../matching/CorrespondingTypeSearcher.java | 109 +++++++++++++++++- ...nterfaceCorrespondingTypeSearcherTest.java | 90 +++++++++++++++ 2 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 org.moreunit.test/test/org/moreunit/matching/InterfaceCorrespondingTypeSearcherTest.java diff --git a/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java b/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java index f820d1cc..b792bd2b 100644 --- a/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java +++ b/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java @@ -3,11 +3,19 @@ import static java.util.Collections.emptySet; import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.ITypeHierarchy; +import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.moreunit.log.LogHandler; import org.moreunit.preferences.Preferences; @@ -26,6 +34,7 @@ */ public class CorrespondingTypeSearcher { + private final IType type; private final ProjectPreferences preferences; private final ClassNameEvaluation nameEvaluation; private final IJavaSearchScope searchScope; @@ -34,8 +43,9 @@ public class CorrespondingTypeSearcher public CorrespondingTypeSearcher(ICompilationUnit compilationUnit, Preferences preferences) { + this.type = compilationUnit.findPrimaryType(); this.preferences = preferences.getProjectView(compilationUnit.getJavaProject()); - nameEvaluation = this.preferences.getTestClassNamePattern().evaluate(compilationUnit.findPrimaryType()); + nameEvaluation = this.preferences.getTestClassNamePattern().evaluate(this.type); IPackageFragmentRoot sourceFolder = nameEvaluation.isTestCase() ? preferences.getTestSourceFolder(compilationUnit.getJavaProject(), PluginTools.getSourceFolder(compilationUnit)) : preferences.getMainSourceFolder(compilationUnit.getJavaProject(), PluginTools.getSourceFolder(compilationUnit)); @@ -74,6 +84,101 @@ public Collection getMatches(boolean alsoIncludeLikelyMatches) private Collection findPotentialTargets(boolean withLikelyMatches) throws CoreException { boolean qualifyWithPackage = ! withLikelyMatches; - return SearchTools.searchFor(nameEvaluation.getAllCorrespondingClassPatterns(qualifyWithPackage), searchScope); + Set patterns = new LinkedHashSet<>(nameEvaluation.getAllCorrespondingClassPatterns(qualifyWithPackage)); + + if(type != null && ! nameEvaluation.isTestCase()) + { + try + { + ITypeHierarchy hierarchy = type.newTypeHierarchy(new NullProgressMonitor()); + for (IType superType : hierarchy.getAllSupertypes(type)) + { + if(! superType.getFullyQualifiedName().startsWith("java.lang.")) + { + ClassNameEvaluation superEval = preferences.getTestClassNamePattern().evaluate(superType); + patterns.addAll(superEval.getAllCorrespondingClassPatterns(qualifyWithPackage)); + } + } + + if(type.isInterface() || Flags.isAbstract(type.getFlags())) + { + for (IType subType : hierarchy.getAllSubtypes(type)) + { + if(! Flags.isAbstract(subType.getFlags()) && ! subType.isInterface()) + { + ClassNameEvaluation subEval = preferences.getTestClassNamePattern().evaluate(subType); + patterns.addAll(subEval.getAllCorrespondingClassPatterns(qualifyWithPackage)); + } + } + } + } + catch (JavaModelException e) + { + LogHandler.getInstance().handleExceptionLog(e); + } + } + + Set matches = SearchTools.searchFor(patterns, searchScope); + + if(nameEvaluation.isTestCase()) + { + Set allMatches = new LinkedHashSet<>(matches); + Set concreteImplementations = new LinkedHashSet<>(); + for (IType match : matches) + { + try + { + if(match.isInterface() || Flags.isAbstract(match.getFlags())) + { + concreteImplementations.addAll(SearchTools.findConcreteSubclasses(match)); + } + } + catch (JavaModelException e) + { + // ignore + } + } + + if(! concreteImplementations.isEmpty()) + { + allMatches.addAll(concreteImplementations); + + for (Iterator it = allMatches.iterator(); it.hasNext();) + { + IType match = it.next(); + try + { + if((match.isInterface() || Flags.isAbstract(match.getFlags())) && ! hasImplementation(match)) + { + it.remove(); + } + } + catch (JavaModelException e) + { + // ignore + } + } + } + + return allMatches; + } + + return matches; + } + + private boolean hasImplementation(IType type) throws JavaModelException + { + for (IMethod method : type.getMethods()) + { + if(Flags.isDefaultMethod(method.getFlags())) + { + return true; + } + if(! Flags.isAbstract(method.getFlags()) && ! type.isInterface()) + { + return true; + } + } + return false; } } diff --git a/org.moreunit.test/test/org/moreunit/matching/InterfaceCorrespondingTypeSearcherTest.java b/org.moreunit.test/test/org/moreunit/matching/InterfaceCorrespondingTypeSearcherTest.java new file mode 100644 index 00000000..76f029c1 --- /dev/null +++ b/org.moreunit.test/test/org/moreunit/matching/InterfaceCorrespondingTypeSearcherTest.java @@ -0,0 +1,90 @@ +package org.moreunit.matching; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collection; + +import org.eclipse.jdt.core.IType; +import org.junit.Test; +import org.moreunit.test.context.ContextTestCase; +import org.moreunit.test.context.Preferences; +import org.moreunit.test.context.Project; + +@Preferences(testClassNameTemplate = "${srcFile}Test", testSrcFolder = "test") +public class InterfaceCorrespondingTypeSearcherTest extends ContextTestCase +{ + @Project(mainCls = "class Foo", testCls = "FooTest") + @Test + public void getMatches_should_return_test_for_class() throws Exception + { + CorrespondingTypeSearcher searcher = new CorrespondingTypeSearcher(context.getCompilationUnit("Foo"), getPreferences()); + Collection matches = searcher.getMatches(false); + + assertThat(matches).extracting("elementName").containsExactly("FooTest"); + } + + @Project(mainCls = "interface Foo", testCls = "FooTest") + @Test + public void getMatches_should_return_test_for_interface() throws Exception + { + context.getPrimaryTypeHandler("Foo").createSubclass("FooImpl"); + + CorrespondingTypeSearcher searcher = new CorrespondingTypeSearcher(context.getCompilationUnit("Foo"), getPreferences()); + Collection matches = searcher.getMatches(false); + + assertThat(matches).extracting("elementName").containsExactly("FooTest"); + } + + @Project(mainCls = "interface Foo", testCls = "FooTest") + @Test + public void getMatches_should_return_implementation_for_interface_test_and_exclude_interface() throws Exception + { + context.getPrimaryTypeHandler("Foo").createSubclass("FooImpl"); + + CorrespondingTypeSearcher searcher = new CorrespondingTypeSearcher(context.getCompilationUnit("FooTest"), getPreferences()); + Collection matches = searcher.getMatches(false); + + // Should return FooImpl and EXCLUDE Foo because Foo is a pure interface + assertThat(matches).extracting("elementName").containsExactly("FooImpl"); + } + + @Project(mainCls = "interface Foo", testCls = "FooTest") + @Test + public void getMatches_should_return_interface_test_for_implementation() throws Exception + { + context.getPrimaryTypeHandler("Foo").createSubclass("FooImpl"); + + CorrespondingTypeSearcher searcher = new CorrespondingTypeSearcher(context.getCompilationUnit("FooImpl"), getPreferences()); + Collection matches = searcher.getMatches(false); + + assertThat(matches).extracting("elementName").contains("FooTest"); + } + + @Project(mainCls = "interface Foo") + @Test + public void getMatches_should_return_interface_for_implementation_test() throws Exception + { + context.getPrimaryTypeHandler("Foo").createSubclass("FooImpl"); + context.getProjectHandler().getTestSrcFolderHandler().createClass("FooImplTest"); + + CorrespondingTypeSearcher searcher = new CorrespondingTypeSearcher(context.getCompilationUnit("FooImplTest"), getPreferences()); + Collection matches = searcher.getMatches(false); + + assertThat(matches).extracting("elementName").containsExactly("FooImpl"); + } + + @Project(mainCls = "interface Foo", testCls = "FooTest") + @Test + public void getMatches_should_include_interface_if_it_has_default_method() throws Exception + { + IType foo = context.getPrimaryTypeHandler("Foo").get(); + foo.createMethod("default void bar() {}", null, true, null); + context.getPrimaryTypeHandler("Foo").createSubclass("FooImpl"); + + CorrespondingTypeSearcher searcher = new CorrespondingTypeSearcher(context.getCompilationUnit("FooTest"), getPreferences()); + Collection matches = searcher.getMatches(false); + + // Should return both Foo and FooImpl because Foo has a default method + assertThat(matches).extracting("elementName").containsExactlyInAnyOrder("Foo", "FooImpl"); + } +} From 40fcdd44333c0b09016976403b6405d17b248759 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:17:57 +0000 Subject: [PATCH 2/4] Support testing against interfaces instead of implementations - Enhanced CorrespondingTypeSearcher to look for tests of supertypes and implementations. - Included concrete implementations in the results when an interface/abstract class is matched. - Excluded 'pure' interfaces/abstract classes from results when concrete implementations are found, unless they have default methods or non-abstract methods. - Optimized subclass search in SearchTools to use SearchEngine instead of full hierarchy. - Added comprehensive tests in InterfaceCorrespondingTypeSearcherTest. Closes #205 Co-authored-by: RoiSoleil <3462260+RoiSoleil@users.noreply.github.com> --- .../matching/CorrespondingTypeSearcher.java | 14 +++++------ .../src/org/moreunit/util/SearchTools.java | 24 ++++++++++++++----- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java b/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java index b792bd2b..1fe844a7 100644 --- a/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java +++ b/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java @@ -48,7 +48,7 @@ public CorrespondingTypeSearcher(ICompilationUnit compilationUnit, Preferences p nameEvaluation = this.preferences.getTestClassNamePattern().evaluate(this.type); IPackageFragmentRoot sourceFolder = nameEvaluation.isTestCase() ? preferences.getTestSourceFolder(compilationUnit.getJavaProject(), PluginTools.getSourceFolder(compilationUnit)) - : preferences.getMainSourceFolder(compilationUnit.getJavaProject(), PluginTools.getSourceFolder(compilationUnit)); + : this.preferences.getMainSourceFolder(PluginTools.getSourceFolder(compilationUnit)); searchScope = SearchScopeSingelton.getInstance().getSearchScope(sourceFolder); } @@ -102,13 +102,11 @@ private Collection findPotentialTargets(boolean withLikelyMatches) throws if(type.isInterface() || Flags.isAbstract(type.getFlags())) { - for (IType subType : hierarchy.getAllSubtypes(type)) + Set foundConcrete = SearchTools.findConcreteSubclasses(type, searchScope); + for (IType subType : foundConcrete) { - if(! Flags.isAbstract(subType.getFlags()) && ! subType.isInterface()) - { - ClassNameEvaluation subEval = preferences.getTestClassNamePattern().evaluate(subType); - patterns.addAll(subEval.getAllCorrespondingClassPatterns(qualifyWithPackage)); - } + ClassNameEvaluation subEval = preferences.getTestClassNamePattern().evaluate(subType); + patterns.addAll(subEval.getAllCorrespondingClassPatterns(qualifyWithPackage)); } } } @@ -130,7 +128,7 @@ private Collection findPotentialTargets(boolean withLikelyMatches) throws { if(match.isInterface() || Flags.isAbstract(match.getFlags())) { - concreteImplementations.addAll(SearchTools.findConcreteSubclasses(match)); + concreteImplementations.addAll(SearchTools.findConcreteSubclasses(match, searchScope)); } } catch (JavaModelException e) diff --git a/org.moreunit.plugin/src/org/moreunit/util/SearchTools.java b/org.moreunit.plugin/src/org/moreunit/util/SearchTools.java index f74c0965..4847201c 100644 --- a/org.moreunit.plugin/src/org/moreunit/util/SearchTools.java +++ b/org.moreunit.plugin/src/org/moreunit/util/SearchTools.java @@ -36,21 +36,33 @@ public static Set searchFor(Collection typeNamePatterns, IJavaSea } public static Set findConcreteSubclasses(IType type) throws JavaModelException + { + return findConcreteSubclasses(type, SearchEngine.createWorkspaceScope()); + } + + public static Set findConcreteSubclasses(IType type, IJavaSearchScope scope) { Set concreteSubclasses = new LinkedHashSet<>(); - ITypeHierarchy hierarchy = type.newTypeHierarchy(new NullProgressMonitor()); - IType[] subtypes = hierarchy.getAllSubtypes(type); - for (IType subtype : subtypes) + try { - if(! Flags.isAbstract(subtype.getFlags()) && ! Flags.isInterface(subtype.getFlags())) + SearchPattern pattern = SearchPattern.createPattern(type, IMPLEMENTORS); + Set found = search(pattern, scope); + for (IType t : found) { - concreteSubclasses.add(subtype); + if(! Flags.isAbstract(t.getFlags()) && ! t.isInterface()) + { + concreteSubclasses.add(t); + } } } + catch (CoreException e) + { + // ignore + } return concreteSubclasses; } - private static Set search(SearchPattern pattern, IJavaSearchScope scope) throws CoreException + public static Set search(SearchPattern pattern, IJavaSearchScope scope) throws CoreException { SearchParticipant[] participants = new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }; MatchCollector collector = new MatchCollector(); From e36203b9182215d4ccecc966634a8761eccbc10d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:54:21 +0000 Subject: [PATCH 3/4] Support testing against interfaces instead of implementations - Enhanced CorrespondingTypeSearcher to look for tests of supertypes and implementations. - Included concrete implementations in the results when an interface/abstract class is matched. - Excluded 'pure' interfaces/abstract classes from results when concrete implementations are found, unless they have default methods or non-abstract methods. - Refined TypeHierarchy usage to avoid compilation issues and improve reliability. - Added comprehensive tests in InterfaceCorrespondingTypeSearcherTest. Closes #205 Co-authored-by: RoiSoleil <3462260+RoiSoleil@users.noreply.github.com> --- .../matching/CorrespondingTypeSearcher.java | 13 ++++++----- .../src/org/moreunit/util/SearchTools.java | 22 +++++-------------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java b/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java index 1fe844a7..a6af057b 100644 --- a/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java +++ b/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java @@ -102,11 +102,14 @@ private Collection findPotentialTargets(boolean withLikelyMatches) throws if(type.isInterface() || Flags.isAbstract(type.getFlags())) { - Set foundConcrete = SearchTools.findConcreteSubclasses(type, searchScope); - for (IType subType : foundConcrete) + IType[] subtypes = hierarchy.getAllSubtypes(type); + for (IType subType : subtypes) { - ClassNameEvaluation subEval = preferences.getTestClassNamePattern().evaluate(subType); - patterns.addAll(subEval.getAllCorrespondingClassPatterns(qualifyWithPackage)); + if(! Flags.isAbstract(subType.getFlags()) && ! subType.isInterface()) + { + ClassNameEvaluation subEval = preferences.getTestClassNamePattern().evaluate(subType); + patterns.addAll(subEval.getAllCorrespondingClassPatterns(qualifyWithPackage)); + } } } } @@ -128,7 +131,7 @@ private Collection findPotentialTargets(boolean withLikelyMatches) throws { if(match.isInterface() || Flags.isAbstract(match.getFlags())) { - concreteImplementations.addAll(SearchTools.findConcreteSubclasses(match, searchScope)); + concreteImplementations.addAll(SearchTools.findConcreteSubclasses(match)); } } catch (JavaModelException e) diff --git a/org.moreunit.plugin/src/org/moreunit/util/SearchTools.java b/org.moreunit.plugin/src/org/moreunit/util/SearchTools.java index 4847201c..2dc3002b 100644 --- a/org.moreunit.plugin/src/org/moreunit/util/SearchTools.java +++ b/org.moreunit.plugin/src/org/moreunit/util/SearchTools.java @@ -36,29 +36,17 @@ public static Set searchFor(Collection typeNamePatterns, IJavaSea } public static Set findConcreteSubclasses(IType type) throws JavaModelException - { - return findConcreteSubclasses(type, SearchEngine.createWorkspaceScope()); - } - - public static Set findConcreteSubclasses(IType type, IJavaSearchScope scope) { Set concreteSubclasses = new LinkedHashSet<>(); - try + ITypeHierarchy hierarchy = type.newTypeHierarchy(new NullProgressMonitor()); + IType[] subtypes = hierarchy.getAllSubtypes(type); + for (IType subtype : subtypes) { - SearchPattern pattern = SearchPattern.createPattern(type, IMPLEMENTORS); - Set found = search(pattern, scope); - for (IType t : found) + if(! Flags.isAbstract(subtype.getFlags()) && ! Flags.isInterface(subtype.getFlags())) { - if(! Flags.isAbstract(t.getFlags()) && ! t.isInterface()) - { - concreteSubclasses.add(t); - } + concreteSubclasses.add(subtype); } } - catch (CoreException e) - { - // ignore - } return concreteSubclasses; } From 74eb5aa2bc1f8c6806175c0d38a354ce26c5e7e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lios=20GILLES?= Date: Fri, 24 Apr 2026 09:08:08 +0200 Subject: [PATCH 4/4] Support testing against interfaces instead of implementations - Fix not working cases --- .../matching/CorrespondingTypeSearcher.java | 9 ++++++++- .../InterfaceCorrespondingTypeSearcherTest.java | 13 +++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java b/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java index a6af057b..4b8ccc41 100644 --- a/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java +++ b/org.moreunit.plugin/src/org/moreunit/matching/CorrespondingTypeSearcher.java @@ -86,6 +86,13 @@ private Collection findPotentialTargets(boolean withLikelyMatches) throws boolean qualifyWithPackage = ! withLikelyMatches; Set patterns = new LinkedHashSet<>(nameEvaluation.getAllCorrespondingClassPatterns(qualifyWithPackage)); + Set matches = SearchTools.searchFor(patterns, searchScope); + + if(matches.size() == 1 && ! matches.iterator().next().isInterface()) + { + return matches; + } + if(type != null && ! nameEvaluation.isTestCase()) { try @@ -119,7 +126,7 @@ private Collection findPotentialTargets(boolean withLikelyMatches) throws } } - Set matches = SearchTools.searchFor(patterns, searchScope); + matches = SearchTools.searchFor(patterns, searchScope); if(nameEvaluation.isTestCase()) { diff --git a/org.moreunit.test/test/org/moreunit/matching/InterfaceCorrespondingTypeSearcherTest.java b/org.moreunit.test/test/org/moreunit/matching/InterfaceCorrespondingTypeSearcherTest.java index 76f029c1..9db951a7 100644 --- a/org.moreunit.test/test/org/moreunit/matching/InterfaceCorrespondingTypeSearcherTest.java +++ b/org.moreunit.test/test/org/moreunit/matching/InterfaceCorrespondingTypeSearcherTest.java @@ -5,6 +5,7 @@ import java.util.Collection; import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; import org.junit.Test; import org.moreunit.test.context.ContextTestCase; import org.moreunit.test.context.Preferences; @@ -15,7 +16,7 @@ public class InterfaceCorrespondingTypeSearcherTest extends ContextTestCase { @Project(mainCls = "class Foo", testCls = "FooTest") @Test - public void getMatches_should_return_test_for_class() throws Exception + public void getMatches_should_return_test_for_class() { CorrespondingTypeSearcher searcher = new CorrespondingTypeSearcher(context.getCompilationUnit("Foo"), getPreferences()); Collection matches = searcher.getMatches(false); @@ -25,7 +26,7 @@ public void getMatches_should_return_test_for_class() throws Exception @Project(mainCls = "interface Foo", testCls = "FooTest") @Test - public void getMatches_should_return_test_for_interface() throws Exception + public void getMatches_should_return_test_for_interface() { context.getPrimaryTypeHandler("Foo").createSubclass("FooImpl"); @@ -37,7 +38,7 @@ public void getMatches_should_return_test_for_interface() throws Exception @Project(mainCls = "interface Foo", testCls = "FooTest") @Test - public void getMatches_should_return_implementation_for_interface_test_and_exclude_interface() throws Exception + public void getMatches_should_return_implementation_for_interface_test_and_exclude_interface() { context.getPrimaryTypeHandler("Foo").createSubclass("FooImpl"); @@ -50,7 +51,7 @@ public void getMatches_should_return_implementation_for_interface_test_and_exclu @Project(mainCls = "interface Foo", testCls = "FooTest") @Test - public void getMatches_should_return_interface_test_for_implementation() throws Exception + public void getMatches_should_return_interface_test_for_implementation() { context.getPrimaryTypeHandler("Foo").createSubclass("FooImpl"); @@ -62,7 +63,7 @@ public void getMatches_should_return_interface_test_for_implementation() throws @Project(mainCls = "interface Foo") @Test - public void getMatches_should_return_interface_for_implementation_test() throws Exception + public void getMatches_should_return_interface_for_implementation_test() { context.getPrimaryTypeHandler("Foo").createSubclass("FooImpl"); context.getProjectHandler().getTestSrcFolderHandler().createClass("FooImplTest"); @@ -75,7 +76,7 @@ public void getMatches_should_return_interface_for_implementation_test() throws @Project(mainCls = "interface Foo", testCls = "FooTest") @Test - public void getMatches_should_include_interface_if_it_has_default_method() throws Exception + public void getMatches_should_include_interface_if_it_has_default_method() throws JavaModelException { IType foo = context.getPrimaryTypeHandler("Foo").get(); foo.createMethod("default void bar() {}", null, true, null);