4444import static org .mockito .ArgumentMatchers .any ;
4545import static org .mockito .ArgumentMatchers .anyInt ;
4646import static org .mockito .ArgumentMatchers .anyString ;
47+ import static org .mockito .ArgumentMatchers .argThat ;
4748import static org .mockito .ArgumentMatchers .eq ;
4849import static org .mockito .ArgumentMatchers .notNull ;
4950import static org .mockito .Mockito .doAnswer ;
@@ -141,6 +142,7 @@ class PrepareAnvilTest {
141142 private EnchantableRegistration registration ;
142143 private ItemStack itemStack ;
143144 private ArgumentCaptor <Runnable > runnableCaptor ;
145+ private AnvilView view ;
144146
145147 @ BeforeEach
146148 void beforeEach () {
@@ -167,22 +169,18 @@ void beforeEach() {
167169 doReturn (config ).when (registration ).getConfig ();
168170
169171 enchanter = new AnvilEnchanter (plugin , registry );
170- }
171172
172- @ AfterEach
173- void afterEach () {
174- var server = Bukkit .getServer ();
175- when (server .getScheduler ()).thenReturn (null );
173+ view = prepareView ();
176174 }
177175
178- private @ NotNull Player prepareEventPlayer () {
176+ private @ NotNull AnvilView prepareView () {
179177 var player = mock (Player .class );
180178 var world = WorldMocks .newWorld ("world" );
181179 when (player .getWorld ()).thenReturn (world );
182180
183181 var inventory = InventoryMocks .newAnvilMock ();
184182 inventory .setItem (0 , itemStack .clone ());
185- var additionItem = new ItemStack ( Material .ENCHANTED_BOOK );
183+ var additionItem = ItemType .ENCHANTED_BOOK . createItemStack ( );
186184 var additionMeta = additionItem .getItemMeta ();
187185 if (additionMeta instanceof EnchantmentStorageMeta storageMeta ) {
188186 storageMeta .addStoredEnchant (enchantment , enchantment .getMaxLevel (), true );
@@ -201,12 +199,17 @@ void afterEach() {
201199
202200 when (player .getOpenInventory ()).thenReturn (view );
203201
204- return player ;
202+ return view ;
203+ }
204+
205+ @ AfterEach
206+ void afterEach () {
207+ var server = Bukkit .getServer ();
208+ when (server .getScheduler ()).thenReturn (null );
205209 }
206210
207211 @ Test
208212 void testInvalidItem () {
209- var view = (AnvilView ) prepareEventPlayer ().getOpenInventory ();
210213 view .getTopInventory ().setItem (0 , null );
211214 var event = spy (new PrepareAnvilEvent (view , null ));
212215 assertDoesNotThrow (() -> enchanter .onPrepareAnvil (event ));
@@ -216,7 +219,6 @@ void testInvalidItem() {
216219
217220 @ Test
218221 void testUnregisteredMaterial () {
219- var view = (AnvilView ) prepareEventPlayer ().getOpenInventory ();
220222 ItemStack badStack = badType .createItemStack ();
221223 view .getTopInventory ().setItem (0 , badStack );
222224 var event = spy (new PrepareAnvilEvent (view , null ));
@@ -228,15 +230,14 @@ void testUnregisteredMaterial() {
228230 @ Test
229231 void testNoPermission () {
230232 doReturn (false ).when (registration ).hasEnchantPermission (notNull (), anyString ());
231- var event = spy (new PrepareAnvilEvent (( AnvilView ) prepareEventPlayer (). getOpenInventory () , null ));
233+ var event = spy (new PrepareAnvilEvent (view , null ));
232234 assertDoesNotThrow (() -> enchanter .onPrepareAnvil (event ));
233235 verify (registration ).hasEnchantPermission (notNull (), anyString ());
234236 verify (event , times (0 )).setResult (any ());
235237 }
236238
237239 @ Test
238240 void testNoChange () {
239- var view = (AnvilView ) prepareEventPlayer ().getOpenInventory ();
240241 view .getTopInventory ().setItem (1 , itemStack .clone ());
241242 var event = spy (new PrepareAnvilEvent (view , null ));
242243
@@ -247,7 +248,6 @@ void testNoChange() {
247248 @ ParameterizedTest
248249 @ MethodSource ("getSlots" )
249250 void testChangePostCalculate (int ... slots ) {
250- var view = (AnvilView ) prepareEventPlayer ().getOpenInventory ();
251251 var event = spy (new PrepareAnvilEvent (view , null ));
252252
253253 assertDoesNotThrow (() -> enchanter .onPrepareAnvil (event ));
@@ -275,9 +275,17 @@ static Collection<Arguments> getSlots() {
275275
276276 @ Test
277277 void testSuccess () {
278- var view = (AnvilView ) prepareEventPlayer ().getOpenInventory ();
279278 var event = spy (new PrepareAnvilEvent (view , null ));
280279
280+ // Because we can't override .equals for mocks and we need to verify that items
281+ // are unchanged before setting the result, we instead want to ensure that "copy"
282+ // is actually the same object.
283+ // This does cause the original item to be manipulated as a side effect when producing the result.
284+ ItemStack base = view .getTopInventory ().getItem (0 );
285+ doReturn (base ).when (base ).clone ();
286+ ItemStack addition = view .getTopInventory ().getItem (1 );
287+ doReturn (addition ).when (addition ).clone ();
288+
281289 assertDoesNotThrow (() -> enchanter .onPrepareAnvil (event ));
282290 verify (event ).setResult (notNull ());
283291 assertThat ("Result is set" , event .getResult (), is (notNullValue ()));
@@ -287,11 +295,11 @@ void testSuccess() {
287295 Runnable task = runnableCaptor .getValue ();
288296
289297 assertDoesNotThrow (task ::run );
290- // var inventory = view.getTopInventory() TODO equals workaround for runnable?
291- // verify(inventory).setItem(
292- // eq(2),
293- // argThat(item -> result.isSimilar(item) && result.getAmount() == item.getAmount())
294- // )
298+ var inventory = view .getTopInventory ();
299+ verify (inventory ).setItem (
300+ eq (2 ),
301+ argThat (item -> result .isSimilar (item ) && result .getAmount () == item .getAmount ())
302+ );
295303 }
296304
297305 }
0 commit comments