package net.kencochrane.raven;

import com.google.common.collect.Iterators;
import mockit.Injectable;
import mockit.Mocked;
import mockit.NonStrictExpectations;
import mockit.Tested;
import net.kencochrane.raven.dsn.Dsn;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.ServiceLoader;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

public class RavenFactoryTest {
    @Tested
    private RavenFactory ravenFactory;
    @Mocked
    private ServiceLoader mockServiceLoader;

    @BeforeMethod
    public void setUp() throws Exception {
        new NonStrictExpectations() {{
            ServiceLoader.load(RavenFactory.class);
            result = mockServiceLoader;
            mockServiceLoader.iterator();
            result = Iterators.emptyIterator();

        }};
    }

    @Test
    public void testGetFactoriesFromServiceLoader(@Injectable final Raven mockRaven,
                                                  @Injectable final Dsn mockDsn) throws Exception {
        new NonStrictExpectations() {{
            mockServiceLoader.iterator();
            result = Iterators.singletonIterator(ravenFactory);
            ravenFactory.createRavenInstance(mockDsn);
            result = mockRaven;
        }};

        Raven raven = RavenFactory.ravenInstance(mockDsn);

        assertThat(raven, is(mockRaven));
    }

    @Test
    public void testGetFactoriesManuallyAdded(@Injectable final Raven mockRaven,
                                              @Injectable final Dsn mockDsn) throws Exception {
        new NonStrictExpectations() {{
            RavenFactory.registerFactory(ravenFactory);
            ravenFactory.createRavenInstance(mockDsn);
            result = mockRaven;
        }};

        Raven raven = RavenFactory.ravenInstance(mockDsn);

        assertThat(raven, is(mockRaven));
    }

    @Test
    public void testRavenInstanceForFactoryNameSucceedsIfFactoryFound(@Injectable final Raven mockRaven,
                                                                     @Injectable final Dsn mockDsn) throws Exception {
        String factoryName = ravenFactory.getClass().getName();
        new NonStrictExpectations() {{
            RavenFactory.registerFactory(ravenFactory);
            ravenFactory.createRavenInstance(mockDsn);
            result = mockRaven;
        }};

        Raven raven = RavenFactory.ravenInstance(mockDsn, factoryName);

        assertThat(raven, is(mockRaven));
    }

    @Test(expectedExceptions = IllegalStateException.class)
    public void testRavenInstanceForFactoryNameFailsIfNoFactoryFound(@Injectable final Raven mockRaven,
                                            @Injectable final Dsn mockDsn) throws Exception {
        String factoryName = "invalidName";
        new NonStrictExpectations() {{
            RavenFactory.registerFactory(ravenFactory);
            ravenFactory.createRavenInstance(mockDsn);
            result = mockRaven;
        }};

        RavenFactory.ravenInstance(mockDsn, factoryName);
    }
}

@@ -83,25 +83,23 @@
  mockit.
-Injectabl
+Delegat
 e;%0Aimpor
@@ -107,22 +107,26 @@
  mockit.
-Mocked
+Injectable
 ;%0Aimport
@@ -216,16 +216,59 @@
 sn.Dsn;%0A
+import org.testng.annotations.AfterMethod;%0A
 import o
@@ -357,31 +357,131 @@
 va.util.
-ServiceLoader;%0A
+HashSet;%0Aimport java.util.Iterator;%0Aimport java.util.ServiceLoader;%0A%0Aimport static mockit.Deencapsulation.setField;
 %0Aimport 
@@ -663,14 +663,18 @@
    @
-Mocked
+Injectable
 %0A   
@@ -789,99 +789,95 @@
     
-new NonStrictExpectations() %7B%7B%0A            ServiceLoader.load(RavenFactory.class
+setField(RavenFactory.class, %22AUTO_REGISTERED_FACTORIES%22, mockServiceLoader
 );%0A
+%0A
         
     
@@ -876,39 +876,38 @@
     
-    result = mockServiceLoader;
+new NonStrictExpectations() %7B%7B
 %0A   
@@ -993,17 +993,16 @@
 ator();%0A
-%0A
         
@@ -1004,32 +1004,339 @@
      %7D%7D;%0A    %7D%0A%0A
+    @AfterMethod%0A    public void tearDown() throws Exception %7B%0A        // Reset the registered factories%0A        setField(RavenFactory.class, %22MANUALLY_REGISTERED_FACTORIES%22, new HashSet%3C%3E());%0A        setField(RavenFactory.class, %22AUTO_REGISTERED_FACTORIES%22, ServiceLoader.load(RavenFactory.class));%0A    %7D%0A%0A
     @Test%0A    pu
@@ -1607,32 +1607,159 @@
         result =
+ new Delegate%3CIterator%3CRavenFactory%3E%3E() %7B%0A                public Iterator%3CRavenFactory%3E iterator() %7B%0A                    return
  Iterators.singl
@@ -1778,32 +1778,65 @@
 (ravenFactory);%0A
+                %7D%0A            %7D;%0A
             rave
@@ -2219,51 +2219,8 @@
 n %7B%0A
-        new NonStrictExpectations() %7B%7B%0A    
     
@@ -2259,32 +2259,71 @@
 (ravenFactory);%0A
+        new NonStrictExpectations() %7B%7B%0A
             rave
@@ -2691,32 +2691,33 @@
                 
+ 
 @Injectable fina
@@ -2818,51 +2818,8 @@
 ();%0A
-        new NonStrictExpectations() %7B%7B%0A    
     
@@ -2858,32 +2858,71 @@
 (ravenFactory);%0A
+        new NonStrictExpectations() %7B%7B%0A
             rave
@@ -3327,32 +3327,57 @@
                 
+                         
 @Injectable fina
@@ -3458,51 +3458,8 @@
 e%22;%0A
-        new NonStrictExpectations() %7B%7B%0A    
     
@@ -3498,32 +3498,71 @@
 (ravenFactory);%0A
+        new NonStrictExpectations() %7B%7B%0A
             rave

Improve tests