/*
 * The MIT License
 *
 *   Copyright (c) 2016, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
 *
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *   THE SOFTWARE.
 */

package io.github.benas.randombeans;

import io.github.benas.randombeans.api.EnhancedRandom;
import io.github.benas.randombeans.api.Randomizer;
import io.github.benas.randombeans.api.RandomizerRegistry;
import io.github.benas.randombeans.beans.Human;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static io.github.benas.randombeans.EnhancedRandomBuilder.aNewEnhancedRandomBuilder;
import static io.github.benas.randombeans.FieldDefinitionBuilder.field;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
@SuppressWarnings("unchecked")
public class EnhancedRandomBuilderTest {

    private static final String NAME = "TestName";

    @Mock
    private Randomizer<String> randomizer;
    @Mock
    private Randomizer humanRandomizer;
    @Mock
    private RandomizerRegistry randomizerRegistry;
    @Mock
    private Human human;

    private EnhancedRandomBuilder enhancedRandomBuilder;

    @Before
    public void setUp() {
        when(randomizer.getRandomValue()).thenReturn(NAME);
        when(humanRandomizer.getRandomValue()).thenReturn(human);
    }

    @Test
    public void builtInstancesShouldBeDistinct() {
        enhancedRandomBuilder = aNewEnhancedRandomBuilder();

        EnhancedRandom enhancedRandom1 = enhancedRandomBuilder.build();
        EnhancedRandom enhancedRandom2 = enhancedRandomBuilder.build();

        assertThat(enhancedRandom1).isNotSameAs(enhancedRandom2);
    }

    @Test
    public void customRandomizerShouldBeRegisteredInAllBuiltInstances() {
        enhancedRandomBuilder = aNewEnhancedRandomBuilder();

        FieldDefinition<?, ?> fieldDefinition = field().named("name").ofType(String.class).inClass(Human.class).get();
        enhancedRandomBuilder.randomize(fieldDefinition, randomizer);

        EnhancedRandom enhancedRandom = enhancedRandomBuilder.build();
        Human human = enhancedRandom.nextObject(Human.class);

        assertThat(human.getName()).isEqualTo(NAME);

        EnhancedRandom enhancedRandom2 = enhancedRandomBuilder.build();
        Human human2 = enhancedRandom2.nextObject(Human.class);

        assertThat(human2.getName()).isEqualTo(NAME);
    }

    @Test
    public void customRandomizerRegistryShouldBeRegisteredInAllBuiltInstances() {
        when(randomizerRegistry.getRandomizer(Human.class)).thenReturn(humanRandomizer);
        enhancedRandomBuilder = aNewEnhancedRandomBuilder().registerRandomizerRegistry(randomizerRegistry);

        EnhancedRandom enhancedRandom = enhancedRandomBuilder.build();
        Human actual = enhancedRandom.nextObject(Human.class);

        assertThat(actual).isEqualTo(human);

        EnhancedRandom enhancedRandom2 = enhancedRandomBuilder.build();
        actual = enhancedRandom2.nextObject(Human.class);

        assertThat(actual).isEqualTo(human);
    }
}

@@ -1610,16 +1610,53 @@
 unner;%0A%0A
+import java.util.function.Supplier;%0A%0A
 import s
@@ -1734,24 +1734,24 @@
 domBuilder;%0A
-
 import stati
@@ -2124,32 +2124,81 @@
 izer;%0A    @Mock%0A
+    private Supplier%3CString%3E supplier;%0A    @Mock%0A
     private Rand
@@ -2470,24 +2470,71 @@
 turn(NAME);%0A
+        when(supplier.get()).thenReturn(NAME);%0A
         when
@@ -3196,24 +3196,24 @@
 ass).get();%0A
-
         enha
@@ -3649,32 +3649,750 @@
 o(NAME);%0A    %7D%0A%0A
+    @Test%0A    public void customSupplierShouldBeRegisteredInAllBuiltInstances() %7B%0A        enhancedRandomBuilder = aNewEnhancedRandomBuilder();%0A%0A        FieldDefinition%3C?, ?%3E fieldDefinition = field().named(%22name%22).ofType(String.class).inClass(Human.class).get();%0A        enhancedRandomBuilder.randomize(fieldDefinition, supplier);%0A%0A        EnhancedRandom enhancedRandom = enhancedRandomBuilder.build();%0A        Human human = enhancedRandom.nextObject(Human.class);%0A%0A        assertThat(human.getName()).isEqualTo(NAME);%0A%0A        EnhancedRandom enhancedRandom2 = enhancedRandomBuilder.build();%0A        Human human2 = enhancedRandom2.nextObject(Human.class);%0A%0A        assertThat(human2.getName()).isEqualTo(NAME);%0A    %7D%0A%0A
     @Test%0A    pu

add test case for registering a supplier with a FieldDefinition