/* * Copyright (c) 2006 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit; import java.io.*; import javax.annotation.*; import org.junit.*; import static org.junit.Assert.*; public final class MockedClassWithSuperClassTest { static class SubclassOfJREClass extends Writer { @Override public void write(@Nonnull char[] cbuf, int off, int len) {} @Override public void flush() {} @Override public void close() { throw new UnsupportedOperationException(); } } static class BaseClass { protected int doSomething() { return 123; } static int staticMethod() { return -1; } } public static class Subclass extends BaseClass { BaseClass getInstance() { return this; } } @Test public void mockedClassExtendingJREClass(@Mocked SubclassOfJREClass mock) throws Exception { // Mocked: assertSame(mock, mock.append("a")); assertSame(mock, mock.append('a')); mock.close(); // Not mocked: Writer w = new Writer() { @Override public void write(@Nonnull char[] cbuf, int off, int len) {} @Override public void flush() {} @Override public void close() {} }; assertSame(w, w.append("Test1")); assertSame(w, w.append('b')); new SubclassOfJREClass() {}.close(); } @Test public void mockedClassExtendingNonJREClass(@Mocked final Subclass mock) { new Expectations() {{ mock.doSomething(); result = 45; times = 3; }}; // Mocked: assertEquals(45, mock.doSomething()); assertEquals(45, new Subclass().doSomething()); // Mocked and matching the recorded expectation: assertEquals(45, new Subclass() {}.doSomething()); // Not mocked: BaseClass b1 = new BaseClass(); BaseClass b2 = new BaseClass() { @Override protected int doSomething() { return super.doSomething() - 23; } }; assertEquals(123, b1.doSomething()); assertEquals(100, b2.doSomething()); } @Test public void cascadingSubclassWithMethodReturningCascadedBaseClassInstance(@Mocked Subclass mock) { // The subclass is already mocked at this point, when the cascaded instance gets created. BaseClass cascaded = mock.getInstance(); assertEquals(0, cascaded.doSomething()); assertEquals(0, mock.doSomething()); } public static final class MockUpForSubclass extends MockUp<Subclass> { @Mock public int doSomething() { return 1; } } @Test public void mockOnlyInstancesOfTheClassSpecifiedToBeMocked() { BaseClass d = new Subclass(); assertEquals(123, d.doSomething()); new MockUpForSubclass(); assertEquals(1, d.doSomething()); assertEquals(123, new BaseClass().doSomething()); assertEquals(1, new Subclass().doSomething()); assertEquals(123, new BaseClass() {}.doSomething()); assertEquals(1, new Subclass() {}.doSomething()); } @Test public void mockOnlyInstancesOfTheClassSpecifiedToBeMocked_usingMockingBridge() { BaseClass d = new Subclass(); assertEquals(123, d.doSomething()); new MockUp<Subclass>() { @Mock int doSomething() { return 2; } }; assertEquals(123, new BaseClass().doSomething()); assertEquals(2, d.doSomething()); assertEquals(2, new Subclass().doSomething()); assertEquals(123, new BaseClass() {}.doSomething()); assertEquals(2, new Subclass() {}.doSomething()); } @Test public void recordExpectationOnStaticMethodFromBaseClass(@Mocked Subclass unused) { new Expectations() {{ BaseClass.staticMethod(); result = 123; }}; assertEquals(123, BaseClass.staticMethod()); } static class BaseClassWithConstructor { BaseClassWithConstructor(@SuppressWarnings("unused") boolean b) {} } static class DerivedClass extends BaseClassWithConstructor { protected DerivedClass() { // TRYCATCHBLOCK instruction appears before call to super, which caused a VerifyError. super(true); try { doSomething(); } catch (RuntimeException ignore) {} } private void doSomething() {} } @Test public void mockSubclassWithConstructorContainingTryCatch_usingMockUp() { new MockUp<DerivedClass>() { @Mock void $init() {} }; new DerivedClass(); } @Test public void mockSubclassWithConstructorContainingTryCatch_usingExpectations(@Mocked DerivedClass mock) { new DerivedClass(); } static class Subclass2 extends BaseClass {} @Test public void recordSameMethodOnDifferentMockedSubclasses(@Mocked final Subclass mock1, @Mocked final Subclass2 mock2) { new Expectations() {{ mock1.doSomething(); result = 1; mock2.doSomething(); result = 2; }}; assertEquals(1, mock1.doSomething()); assertEquals(2, mock2.doSomething()); } @Test public void recordMethodOnMockedBaseClassButReplayOnSubclassInstance(@Mocked final BaseClass baseMock) { new Expectations() {{ baseMock.doSomething(); result = 45; }}; Subclass derived = new Subclass(); assertEquals(45, derived.doSomething()); assertEquals(45, baseMock.doSomething()); } }