/* * Copyright (c) 2006 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit; import java.net.*; import java.util.*; import org.junit.*; import org.junit.rules.*; import static org.junit.Assert.*; import mockit.internal.*; public final class StrictExpectationsTest { @Rule public final ExpectedException thrown = ExpectedException.none(); static class Collaborator { private int value; Collaborator() {} Collaborator(int value) { this.value = value; } static String doInternal() { return "123"; } void provideSomeService() {} protected native boolean nativeMethod(); String doSomething(URL url) { return url.toString(); } int getValue() { return value; } void setValue(int value) { this.value = value; } } @Test public void expectOnlyOneInvocationButExerciseOthersDuringReplay(@Mocked final Collaborator mock) { thrown.expect(UnexpectedInvocation.class); new StrictExpectations() {{ mock.provideSomeService(); }}; mock.provideSomeService(); mock.setValue(1); } @Test public void recordNothingOnLocalMockedTypeAndExerciseItDuringReplay(@Mocked Collaborator mock) { mock.provideSomeService(); } @Test public void recordEmptyBlockOnLocalMockedTypeAndExerciseItDuringReplay(@Mocked Collaborator mock) { new StrictExpectations() {}; mock.provideSomeService(); } @Test public void expectNothingOnMockedTypeButExerciseItDuringReplay(@Mocked final Collaborator mock) { thrown.expect(UnexpectedInvocation.class); new StrictExpectations() {{ mock.setValue(anyInt); times = 0; }}; mock.setValue(2); } @Test public void mockInterface(@Mocked final Runnable mock) { new StrictExpectations() {{ mock.run(); }}; mock.run(); } public interface IA {} public interface IB extends IA {} public interface IC { boolean doSomething(IB b); } @Test public void mockInterfaceWhichExtendsAnother(@Mocked final IB b, @Mocked final IC c) { new StrictExpectations() {{ c.doSomething(b); result = false; c.doSomething(b); result = true; }}; assertFalse(c.doSomething(b)); assertTrue(c.doSomething(b)); } public abstract static class AbstractCollaborator { String doSomethingConcrete() { return "test"; } protected abstract void doSomethingAbstract(); } @Test public void mockAbstractClass(@Mocked final AbstractCollaborator mock) { new StrictExpectations() {{ mock.doSomethingConcrete(); mock.doSomethingAbstract(); }}; mock.doSomethingConcrete(); mock.doSomethingAbstract(); } @Test public void mockClassWithoutDefaultConstructor(@Mocked Dummy mock) { assertNotNull(mock); } static class Dummy { @SuppressWarnings("unused") Dummy(int i) {} } static final class SubCollaborator extends Collaborator { @Override int getValue() { return 1 + super.getValue(); } int getValue(int i) { return i + super.getValue(); } } @Test public void mockSubclass(@Mocked final SubCollaborator mock) { new StrictExpectations() {{ new SubCollaborator(); mock.provideSomeService(); mock.getValue(); result = 1; }}; SubCollaborator collaborator = new SubCollaborator(); collaborator.provideSomeService(); assertEquals(1, collaborator.getValue()); } @Test public void mockSuperClass(@Mocked final Collaborator mock) { new StrictExpectations() {{ mock.getValue(); times = 2; returns(1, 2); }}; SubCollaborator collaborator = new SubCollaborator(); assertEquals(2, collaborator.getValue()); assertEquals(3, collaborator.getValue(1)); } @Test public void mockClassWithMethodsOfAllReturnTypesReturningDefaultValues( @Mocked final ClassWithMethodsOfEveryReturnType mock) { new StrictExpectations() {{ mock.getBoolean(); mock.getChar(); mock.getByte(); mock.getShort(); mock.getInt(); mock.getLong(); mock.getFloat(); mock.getDouble(); mock.getObject(); mock.getElements(); }}; assertFalse(mock.getBoolean()); assertEquals('\0', mock.getChar()); assertEquals(0, mock.getByte()); assertEquals(0, mock.getShort()); assertEquals(0, mock.getInt()); assertEquals(0L, mock.getLong()); assertEquals(0.0, mock.getFloat(), 0.0); assertEquals(0.0, mock.getDouble(), 0.0); assertNull(mock.getObject()); assertFalse(mock.getElements().hasMoreElements()); } static class ClassWithMethodsOfEveryReturnType { boolean getBoolean() { return true; } char getChar() { return 'A' ; } byte getByte() { return 1; } short getShort() { return 1; } int getInt() { return 1; } long getLong() { return 1; } float getFloat() { return 1.0F; } double getDouble() { return 1.0; } Object getObject() { return new Object(); } Enumeration<?> getElements() { return null; } ClassWithMethodsOfEveryReturnType returnSameType() { return null; } } @Test public void replayWithUnexpectedStaticMethodInvocation(@Mocked final Collaborator mock) { thrown.expect(UnexpectedInvocation.class); new StrictExpectations() {{ mock.getValue(); }}; Collaborator.doInternal(); } @Test public void replayWithMissingExpectedMethodInvocation(@Mocked final Collaborator mock) { thrown.expect(MissingInvocation.class); new StrictExpectations() {{ mock.setValue(123); }}; } @Test public void defineTwoConsecutiveReturnValues(@Mocked final Collaborator mock) { new StrictExpectations() {{ mock.getValue(); result = 1; result = 2; }}; assertEquals(1, mock.getValue()); assertEquals(2, mock.getValue()); } @Test public void mockNativeMethodUsingFullMocking(@Mocked final Collaborator mock) { new StrictExpectations() {{ mock.nativeMethod(); result = true; }}; assertTrue(mock.nativeMethod()); } @Test public void mockNativeMethodUsingPartialMocking() { Collaborator col = new Collaborator(); new MockUp<Collaborator>() { @Mock boolean nativeMethod() { return true; } }; assertTrue(col.nativeMethod()); } @Test public void mockSystemGetenvMethod(@Mocked System mockedSystem) { new StrictExpectations() {{ System.getenv("envVar"); result = "."; }}; assertEquals(".", System.getenv("envVar")); } @Test public void failureFromUnexpectedInvocationInAnotherThread(@Mocked final Collaborator mock) throws Exception { thrown.expect(UnexpectedInvocation.class); Thread t = new Thread() { @Override public void run() { mock.provideSomeService(); } }; new StrictExpectations() {{ mock.getValue(); }}; mock.getValue(); t.start(); t.join(); } public interface InterfaceWithStaticInitializer { Object X = "x"; } @Test public void mockInterfaceWithStaticInitializer(@Mocked InterfaceWithStaticInitializer mock) { assertNotNull(mock); assertEquals("x", InterfaceWithStaticInitializer.X); } @Test public void recordingExpectationOnMethodWithOneArgumentButReplayingWithAnotherShouldProduceUsefulErrorMessage( @Mocked final Collaborator mock) throws Exception { final URL expectedURL = new URL("http://expected"); new StrictExpectations() {{ mock.doSomething(expectedURL); }}; mock.doSomething(expectedURL); URL anotherURL = new URL("http://another"); try { mock.doSomething(anotherURL); fail(); } catch (UnexpectedInvocation e) { assertTrue(e.getMessage().contains(anotherURL.toString())); } } @Test public void recordExpectationInMethodOfExpectationBlockInsteadOfConstructor(@Mocked final Collaborator mock) { new StrictExpectations() { { recordExpectation(); } private void recordExpectation() { mock.getValue(); result = 123; } }; assertEquals(123, mock.getValue()); } @Test public void recordExpectationsOnMethodReturningOwnType(@Mocked final ClassWithMethodsOfEveryReturnType mock) { ClassWithMethodsOfEveryReturnType nonMock = new ClassWithMethodsOfEveryReturnType(); new StrictExpectations() {{ mock.returnSameType(); mock.returnSameType(); }}; assertSame(mock, mock.returnSameType()); assertSame(mock, nonMock.returnSameType()); } }