package com.github.rowanhill.boneidle;

import com.github.rowanhill.boneidle.LazyFactory;
import com.github.rowanhill.boneidle.LazyLoadWith;
import org.junit.Before;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class LazyFactoryTest {
    private MyClass original;
    private MyClass proxy;

    @Before
    public void setUp() {
        // given
        original = new MyClass();

        // when
        proxy = LazyFactory.proxy(original);
    }

    @Test
    public void lazyProxiesAreAssignableToProxiedType() {
        // (This is a bit redundant, given the compiler is happy with the above assignment)
        assertThat(proxy).isInstanceOf(MyClass.class);
    }

    @Test
    public void unannotatedMethodsAreUnaffected() {
        // when
        String unannotated = proxy.unannotatedMethod();

        // then
        assertThat(unannotated).isEqualTo(original.unannotatedMethod());
    }

    @Test
    public void lazyLoadWithAnnotationCallsLoaderMethodBeforeInvokingOriginalMethod() {
        // when
        String lazyLoadedString = proxy.getLazyLoadedString();

        // then
        assertThat(lazyLoadedString).isEqualTo(MyClass.LAZY_LOADED_STRING_CONTENT);
    }

    @Test
    public void loaderMethodIsOnlyInvokedOnceWhenLazyMethodIsInvokedMultipleTimes() {
        // when
        proxy.getLazyLoadedString();
        proxy.getLazyLoadedString();

        // then
        assertThat(original.lazyLoadCount).isEqualTo(1);
    }

    @Test
    public void loaderMethodIsOnlyInvokedOnceWhenMultipleLazyMethodsWithSameLoaderAreInvoked() {
        // when
        proxy.getLazyLoadedString();
        proxy.getOtherLazyLoadedString();

        // then
        assertThat(original.lazyLoadCount).isEqualTo(1);
    }

    static class MyClass {
        public static final String LAZY_LOADED_STRING_CONTENT = "This string was loaded lazily";
        private String lazyLoadedString = null;
        private String otherLazyLoadedString = null;
        private int lazyLoadCount = 0;

        String unannotatedMethod() {
            return "Unannotated methods should not be affected by proxying";
        }

        @LazyLoadWith("loadLazyLoadedString")
        String getLazyLoadedString() {
            return lazyLoadedString;
        }

        @LazyLoadWith("loadLazyLoadedString")
        String getOtherLazyLoadedString() {
            return otherLazyLoadedString;
        }

        @SuppressWarnings("UnusedDeclaration")
        private void loadLazyLoadedString() {
            lazyLoadCount++;
            lazyLoadedString = LAZY_LOADED_STRING_CONTENT;
            otherLazyLoadedString = "Other lazy loaded string";
        }
    }
}

@@ -37,109 +37,8 @@
 e;%0A%0A
-import com.github.rowanhill.boneidle.LazyFactory;%0Aimport com.github.rowanhill.boneidle.LazyLoadWith;%0A
 impo
@@ -58,16 +58,16 @@
 Before;%0A
+
 import o
@@ -1357,32 +1357,38 @@
 riginal.lazyLoad
+String
 Count).isEqualTo
@@ -1650,24 +1650,685 @@
 nal.lazyLoad
+StringCount).isEqualTo(1);%0A    %7D%0A%0A    @Test%0A    public void secondLoaderMethodNotInvokedForUnassociatedMethods() %7B%0A        // when%0A        proxy.getLazyLoadedString();%0A%0A        // then%0A        assertThat(original.lazyLoadIntegerCount).isEqualTo(0);%0A    %7D%0A%0A    @Test%0A    public void multipleLoaderMethodsInvokedOnceEachByMultipleUnassociatedLazyLoadedMethodInvocations() %7B%0A        // when%0A        proxy.getLazyLoadedString();%0A        proxy.getLazyLoadedString();%0A        proxy.getLazyLoadedInteger();%0A        proxy.getLazyLoadedInteger();%0A%0A        // then%0A        assertThat(original.lazyLoadStringCount).isEqualTo(1);%0A        assertThat(original.lazyLoadInteger
 Count).isEqu
@@ -2467,16 +2467,88 @@
 azily%22;%0A
+        public static final Integer LAZY_LOADED_INTEGER_CONTENT = 123;%0A%0A
         
@@ -2644,36 +2644,140 @@
 ll;%0A
-        private int lazyLoad
+%0A        private Integer lazyLoadedInteger = null;%0A%0A        private int lazyLoadStringCount = 0;%0A        private int lazyLoadInteger
 Coun
@@ -3177,32 +3177,169 @@
 ing;%0A        %7D%0A%0A
+        @LazyLoadWith(%22loadLazyLoadedInteger%22)%0A        Integer getLazyLoadedInteger() %7B%0A            return lazyLoadedInteger;%0A        %7D%0A%0A
         @Suppres
@@ -3435,16 +3435,22 @@
 lazyLoad
+String
 Count++;
@@ -3509,16 +3509,16 @@
 ONTENT;%0A
-
         
@@ -3582,16 +3582,218 @@
        %7D
+%0A%0A        @SuppressWarnings(%22UnusedDeclaration%22)%0A        private void loadLazyLoadedInteger() %7B%0A            lazyLoadIntegerCount++;%0A            lazyLoadedInteger = LAZY_LOADED_INTEGER_CONTENT;%0A        %7D
 %0A    %7D%0A%7D

Add tests for multiple lazy loader methods in the same class