package uk.co.littlemike.jextend;

import org.junit.BeforeClass;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static uk.co.littlemike.jextend.JExtend.resetServiceLoader;

@SuppressWarnings("unchecked")
public abstract class BaseExtensionTest {

    List list = new ArrayList();

    @BeforeClass
    public static void unloadImplementation() {
        resetServiceLoader();
    }

    @Test
    public void canExtendUsingImplementationOnClasspath() {
        ListExtension extendedList = extendListWith(ListExtension.class);

        assertThat(extendedList).isNotNull();
    }

    @Test
    public void delegatesMethodCallsToUnderlyingObject() {
        ListExtension extendedList = extendListWith(ListExtension.class);

        list.add("Direct");
        extendedList.add("Proxy");
        assertThat(list).containsExactly("Direct", "Proxy");
        assertThat(extendedList).containsExactly("Direct", "Proxy");
    }
    
    interface TalkingList extends List {
        default String greeting() {
            return "Hello world!";
        }
    }

    @Test
    public void executesDefaultMethod() {
        TalkingList talkingList = extendListWith(TalkingList.class);

        assertThat(talkingList.greeting()).isEqualTo("Hello world!");
    }

    private <E extends List> E extendListWith(Class<E> extensionInterface) {
        return JExtend.getExtension(List.class, extensionInterface).extend(list);
    }
}

@@ -1133,24 +1133,101 @@
 %22;%0A        %7D
+%0A%0A        default String sizeDescription() %7B return %22My size is %22 + size(); %7D
 %0A    %7D%0A%0A    
@@ -1417,24 +1417,1081 @@
 !%22);%0A    %7D%0A%0A
+    @Test%0A    public void defaultMethodMayCallDelegateMethod() %7B%0A        TalkingList talkingList = extendListWith(TalkingList.class);%0A        talkingList.add(%22Item%22);%0A%0A        assertThat(talkingList.sizeDescription()).isEqualTo(%22My size is 1%22);%0A    %7D%0A%0A    public interface Base %7B%0A        default String getName() %7B%0A            return %22Base%22;%0A        %7D%0A%0A        default String sayName() %7B%0A            return %22I am %22 + getName();%0A        %7D%0A    %7D%0A%0A    public interface Extension extends Base %7B%0A        @Override%0A        default String getName() %7B%0A            return %22Extension%22;%0A        %7D%0A    %7D%0A%0A    @Test%0A    public void delegatedMethodCallDoesNotCallOverriddenMethod() %7B%0A        Base base = new Base() %7B%7D;%0A        Extension extension = JExtend.getExtension(Base.class, Extension.class).extend(base);%0A%0A        assertThat(base.getName()).isEqualTo(%22Base%22);%0A        assertThat(base.sayName()).isEqualTo(%22I am Base%22);%0A        assertThat(extension.getName()).isEqualTo(%22Extension%22);%0A        assertThat(extension.sayName()).isEqualTo(%22I am Base%22); // NOTE!%0A    %7D%0A%0A
     private 

Add additional test cases to cover more expected behaviour