package org.mockitousage.annotation;

import org.fest.assertions.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.exceptions.base.MockitoException;
import org.mockito.internal.util.MockUtil;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockitousage.examples.use.ArticleCalculator;
import org.mockitousage.examples.use.ArticleDatabase;
import org.mockitousage.examples.use.ArticleManager;

import java.util.HashSet;
import java.util.Set;

import static org.junit.Assert.*;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class MockInjectionUsingConstructorTest {
    private MockUtil mockUtil = new MockUtil();

    @Mock private ArticleCalculator calculator;
    @Mock private ArticleDatabase database;

    @InjectMocks private ArticleManager articleManager;
    @Spy @InjectMocks private ArticleManager spiedArticleManager;


    @InjectMocks private ArticleVisitor should_be_initialized_several_times;

    @Test
    public void shouldNotFailWhenNotInitialized() {
        assertNotNull(articleManager);
    }

    @Test(expected = IllegalArgumentException.class)
    public void innerMockShouldRaiseAnExceptionThatChangesOuterMockBehavior() {
        when(calculator.countArticles("new")).thenThrow(new IllegalArgumentException());

        articleManager.updateArticleCounters("new");
    }

    @Test
    public void mockJustWorks() {
        articleManager.updateArticleCounters("new");
    }

    @Test
    public void constructor_is_called_for_each_test() throws Exception {
        int number_of_test_before_including_this_one = 4;
        assertEquals(number_of_test_before_including_this_one, articleVisitorInstantiationCount);
        assertEquals(number_of_test_before_including_this_one, articleVisitorMockInjectedInstances.size());
    }

    @Test
    public void objects_created_with_constructor_initialization_can_be_spied() throws Exception {
        assertFalse(mockUtil.isMock(articleManager));
        assertTrue(mockUtil.isMock(spiedArticleManager));
    }

    @Test
    public void should_report_failure_only_when_object_initialization_throws_exception() throws Exception {
        class ATest {
            @Mock Set set;
            @InjectMocks FailingConstructor failingConstructor;
        }

        try {
            MockitoAnnotations.initMocks(new ATest());
            fail();
        } catch (MockitoException e) {
            Assertions.assertThat(e.getMessage()).contains("failingConstructor").contains("constructor").contains("threw an exception");
            Assertions.assertThat(e.getCause()).isInstanceOf(IllegalStateException.class);
        }
    }

    private static int articleVisitorInstantiationCount = 0;
    private static Set<Object> articleVisitorMockInjectedInstances = new HashSet<Object>();

    private static class ArticleVisitor {
        public ArticleVisitor(ArticleCalculator calculator) {
            articleVisitorInstantiationCount++;
            articleVisitorMockInjectedInstances.add(calculator);
        }
    }

    private static class FailingConstructor {
        FailingConstructor(Set set) {
            throw new IllegalStateException("always fail");
        }
    }

}

@@ -66,24 +66,49 @@
 Assertions;%0A
+import org.junit.Ignore;%0A
 import org.j
@@ -118,16 +118,16 @@
 t.Test;%0A
-
 import o
@@ -1720,16 +1720,24 @@
     int 
+minimum_
 number_o
@@ -1753,31 +1753,12 @@
 fore
-_including_this_one
  = 
-4
+3
 ;%0A  
@@ -1767,203 +1767,227 @@
     
-a
+A
 ssert
-Equals(number_of_test_before_including_this_one, articleVisitorInstantiationCount);%0A        assertEquals(number_of_test_before_including_this_one, articleVisitorMockInjectedInstances.size()
+ions.assertThat(articleVisitorInstantiationCount).isGreaterThan(minimum_number_of_test_before);%0A        Assertions.assertThat(articleVisitorMockInjectedInstances.size()).isGreaterThan(minimum_number_of_test_before
 );%0A 
@@ -2340,131 +2340,8 @@
 on %7B
-%0A        class ATest %7B%0A            @Mock Set set;%0A            @InjectMocks FailingConstructor failingConstructor;%0A        %7D
 %0A%0A  
@@ -3253,17 +3253,195 @@
       %7D%0A
-
     %7D%0A%0A
+    @Ignore(%22don't run this code in the test runner%22)%0A    private static class ATest %7B%0A        @Mock Set set;%0A        @InjectMocks FailingConstructor failingConstructor;%0A    %7D%0A%0A%0A
 %7D%0A

fix test code to make it work in jenkins