1 /* 2 * Copyright (c) 2020 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 package org.mockitoinline; 6 7 import static junit.framework.TestCase.assertEquals; 8 import static junit.framework.TestCase.assertNull; 9 import static junit.framework.TestCase.assertTrue; 10 import static org.assertj.core.api.Assertions.assertThatThrownBy; 11 import static org.mockito.Mockito.times; 12 import static org.mockito.Mockito.verify; 13 import static org.mockito.Mockito.when; 14 15 import java.util.Collections; 16 import java.util.concurrent.atomic.AtomicReference; 17 18 import org.junit.Test; 19 import org.mockito.MockedConstruction; 20 import org.mockito.Mockito; 21 import org.mockito.exceptions.base.MockitoException; 22 23 public final class ConstructionMockTest { 24 25 @Test testConstructionMockSimple()26 public void testConstructionMockSimple() { 27 assertEquals("foo", new Dummy().foo()); 28 try (MockedConstruction<Dummy> ignored = Mockito.mockConstruction(Dummy.class)) { 29 assertNull(new Dummy().foo()); 30 } 31 assertEquals("foo", new Dummy().foo()); 32 } 33 34 @Test testConstructionMockCollection()35 public void testConstructionMockCollection() { 36 try (MockedConstruction<Dummy> dummy = Mockito.mockConstruction(Dummy.class)) { 37 assertEquals(0, dummy.constructed().size()); 38 Dummy mock = new Dummy(); 39 assertEquals(1, dummy.constructed().size()); 40 assertTrue(dummy.constructed().contains(mock)); 41 } 42 } 43 44 @Test testConstructionMockDefaultAnswer()45 public void testConstructionMockDefaultAnswer() { 46 try (MockedConstruction<Dummy> ignored = Mockito.mockConstructionWithAnswer(Dummy.class, invocation -> "bar")) { 47 assertEquals("bar", new Dummy().foo()); 48 } 49 } 50 51 @Test testConstructionMockDefaultAnswerMultiple()52 public void testConstructionMockDefaultAnswerMultiple() { 53 try (MockedConstruction<Dummy> ignored = Mockito.mockConstructionWithAnswer(Dummy.class, invocation -> "bar", invocation -> "qux")) { 54 assertEquals("bar", new Dummy().foo()); 55 assertEquals("qux", new Dummy().foo()); 56 assertEquals("qux", new Dummy().foo()); 57 } 58 } 59 60 /** 61 * Tests issue #2544 62 */ 63 @Test testConstructionMockDefaultAnswerMultipleMoreThanTwo()64 public void testConstructionMockDefaultAnswerMultipleMoreThanTwo() { 65 try (MockedConstruction<Dummy> ignored = Mockito.mockConstructionWithAnswer(Dummy.class, invocation -> "bar", invocation -> "qux", invocation -> "baz")) { 66 assertEquals("bar", new Dummy().foo()); 67 assertEquals("qux", new Dummy().foo()); 68 assertEquals("baz", new Dummy().foo()); 69 assertEquals("baz", new Dummy().foo()); 70 } 71 } 72 73 @Test testConstructionMockPrepared()74 public void testConstructionMockPrepared() { 75 try (MockedConstruction<Dummy> ignored = Mockito.mockConstruction(Dummy.class, (mock, context) -> when(mock.foo()).thenReturn("bar"))) { 76 assertEquals("bar", new Dummy().foo()); 77 } 78 } 79 80 81 @Test testConstructionMockContext()82 public void testConstructionMockContext() { 83 try (MockedConstruction<Dummy> ignored = Mockito.mockConstruction(Dummy.class, (mock, context) -> { 84 assertEquals(1, context.getCount()); 85 assertEquals(Collections.singletonList("foobar"), context.arguments()); 86 assertEquals(mock.getClass().getDeclaredConstructor(String.class), context.constructor()); 87 when(mock.foo()).thenReturn("bar"); 88 })) { 89 assertEquals("bar", new Dummy("foobar").foo()); 90 } 91 } 92 93 @Test testConstructionMockDoesNotAffectDifferentThread()94 public void testConstructionMockDoesNotAffectDifferentThread() throws InterruptedException { 95 try (MockedConstruction<Dummy> ignored = Mockito.mockConstruction(Dummy.class)) { 96 Dummy dummy = new Dummy(); 97 when(dummy.foo()).thenReturn("bar"); 98 assertEquals("bar", dummy.foo()); 99 verify(dummy).foo(); 100 AtomicReference<String> reference = new AtomicReference<>(); 101 Thread thread = new Thread(() -> reference.set(new Dummy().foo())); 102 thread.start(); 103 thread.join(); 104 assertEquals("foo", reference.get()); 105 when(dummy.foo()).thenReturn("bar"); 106 assertEquals("bar", dummy.foo()); 107 verify(dummy, times(2)).foo(); 108 } 109 } 110 111 @Test testConstructionMockCanCoexistWithMockInDifferentThread()112 public void testConstructionMockCanCoexistWithMockInDifferentThread() throws InterruptedException { 113 try (MockedConstruction<Dummy> ignored = Mockito.mockConstruction(Dummy.class)) { 114 Dummy dummy = new Dummy(); 115 when(dummy.foo()).thenReturn("bar"); 116 assertEquals("bar", dummy.foo()); 117 verify(dummy).foo(); 118 AtomicReference<String> reference = new AtomicReference<>(); 119 Thread thread = new Thread(() -> { 120 try (MockedConstruction<Dummy> ignored2 = Mockito.mockConstruction(Dummy.class)) { 121 Dummy other = new Dummy(); 122 when(other.foo()).thenReturn("qux"); 123 reference.set(other.foo()); 124 } 125 }); 126 thread.start(); 127 thread.join(); 128 assertEquals("qux", reference.get()); 129 assertEquals("bar", dummy.foo()); 130 verify(dummy, times(2)).foo(); 131 } 132 } 133 134 @Test testConstructionMockMustBeExclusiveInScopeWithinThread()135 public void testConstructionMockMustBeExclusiveInScopeWithinThread() { 136 assertThatThrownBy( 137 () -> { 138 try ( 139 MockedConstruction<Dummy> dummy = Mockito.mockConstruction(Dummy.class); 140 MockedConstruction<Dummy> duplicate = Mockito.mockConstruction(Dummy.class)) { 141 } 142 }) 143 .isInstanceOf(MockitoException.class) 144 .hasMessageContaining("static mocking is already registered in the current thread"); 145 } 146 147 @Test testConstructionMockMustNotTargetAbstractClass()148 public void testConstructionMockMustNotTargetAbstractClass() { 149 assertThatThrownBy( 150 () -> { 151 Mockito.mockConstruction(Runnable.class).close(); 152 }) 153 .isInstanceOf(MockitoException.class) 154 .hasMessageContaining("It is not possible to construct primitive types or abstract types"); 155 } 156 157 static class Dummy { 158 159 Dummy()160 public Dummy() { 161 } 162 Dummy(String value)163 public Dummy(String value) { 164 } 165 foo()166 String foo() { 167 return "foo"; 168 } 169 } 170 } 171