package examples.inheritance;

import com.google.common.collect.Multiset;
import mockit.Injectable;
import mockit.Mocked;
import mockit.NonStrictExpectations;
import org.junit.Test;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

public class FruitBasketTest {
    /**
     * In this test we see that Banana gets mocked also because it inherits from Produce.
     *
     */
    @Test
    public void mockAppleAndProduceFactory(@Mocked final Apple mockApple, @Mocked("factory") final Produce mockProduce) throws Exception {
        final Banana testBanana = new Banana("orange");

        new NonStrictExpectations() {{
            mockApple.getColor();
            result = "red"; // only produce red apples

            mockApple.isWormy();
            result = false;

            Produce.factory(Produce.Type.APPLE, anyString);
            result = mockApple;

            Produce.factory(Produce.Type.BANANA, anyString);
            result = testBanana;
        }};

        FruitBasket basket = new FruitBasket();
        basket.fillBasket();
        Multiset<String> colors = basket.getColorCounts();
        assertThat("red", colors.count("red"), is(3));
        assertThat("green", colors.count("green"), is(0));
        assertThat("yellow", colors.count("yellow"), is(0));
        assertThat("orange", colors.count("orange"), is(0));

        Banana myBanana = new Banana("green");
        assertThat(myBanana.getColor(), is("red"));
    }

    /**
     * This test shows how Injectable can be used to to isolate a mock.
     */
    @Test
    public void usingInjectableOnApple(@Injectable final Apple mockApple, @Mocked final Produce mockProduce) throws Exception {
        final Banana testBanana = new Banana("orange");

        new NonStrictExpectations() {{
            mockApple.getColor();
            result = "red"; // only produce red apples

            mockApple.isWormy();
            result = false;

            Produce.factory(Produce.Type.APPLE, anyString);
            result = mockApple;

            Produce.factory(Produce.Type.BANANA, anyString);
            result = testBanana;
        }};

        FruitBasket basket = new FruitBasket();
        basket.fillBasket();
        Multiset<String> colors = basket.getColorCounts();
        assertThat("red", colors.count("red"), is(2));
        assertThat("green", colors.count("green"), is(0));
        assertThat("yellow", colors.count("yellow"), is(0));
        assertThat("orange", colors.count("orange"), is(1));

        Banana myBanana = new Banana("green");
        assertThat(myBanana.getColor(), is("green"));
    }
}

@@ -67,16 +67,44 @@
 ltiset;%0A
+import mockit.Expectations;%0A
 import m
@@ -518,54 +518,8 @@
 pple
-, @Mocked(%22factory%22) final Produce mockProduce
 ) th
@@ -600,33 +600,24 @@
         new 
-NonStrict
 Expectations
@@ -621,164 +621,25 @@
 ons(
-) %7B%7B%0A            mockApple.getColor();%0A            result = %22red%22; // only produce red apples%0A%0A            mockApple.isWormy();%0A            result = false;%0A
+Produce.class) %7B%7B
 %0A   
@@ -827,32 +827,164 @@
 a;%0A        %7D%7D;%0A%0A
+        new Expectations() %7B%7B%0A            mockApple.getColor();%0A            result = %22red%22; // only produce red apples%0A        %7D%7D;%0A%0A
         FruitBas
@@ -1620,43 +1620,8 @@
 pple
-, @Mocked final Produce mockProduce
 ) th
@@ -1706,25 +1706,16 @@
     new 
-NonStrict
 Expectat
@@ -1711,32 +1711,45 @@
 ew Expectations(
+Produce.class
 ) %7B%7B%0A           
@@ -1753,84 +1753,87 @@
     
-mockApple.getColor();%0A            result = %22red%22; // only produce red a
+Produce.factory(Produce.Type.APPLE, anyString);%0A            result = mockA
 pple
-s
+;
 %0A%0A  
@@ -1846,149 +1846,230 @@
     
-mockApple.isW
+Produce.fact
 or
-m
 y(
-);%0A            result = false;%0A%0A            Produce.factory(Produce.Type.APPLE, anyString);%0A            result = mockA
+Produce.Type.BANANA, anyString);%0A            result = testBanana;%0A        %7D%7D;%0A%0A        new NonStrictExpectations() %7B%7B%0A            mockApple.getColor();%0A            result = %22red%22; // only produce red a
 pple
-;
+s
 %0A%0A  
@@ -2082,54 +2082,26 @@
     
-Produce.fact
+mockApple.isW
 or
+m
 y(
-Produce.Type.BANANA, anyString
 );%0A 
@@ -2116,34 +2116,29 @@
    result = 
-testBanana
+false
 ;%0A        %7D%7D

Update FruitBasketTest to use Dynamic Partial Mocking