/* * Copyright (c) 2006-2011 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit; import java.io.*; import java.net.*; import java.nio.channels.*; import java.util.*; import org.junit.*; import static org.junit.Assert.*; public final class CascadingParametersAndLocalFieldsTest { static class Foo { Bar getBar() { return null; } static Bar globalBar() { return null; } void doSomething(String s) { throw new RuntimeException(s); } int getIntValue() { return 1; } private Boolean getBooleanValue() { return true; } final List<Integer> getList() { return null; } } static class Bar { Bar() { throw new RuntimeException(); } int doSomething() { return 1; } Baz getBaz() { return null; } AnEnum getEnum() { return null; } static String staticMethod() { return "notMocked"; } } public interface Baz { void runIt(); Date getDate(); } enum AnEnum { First, Second, Third } @Test public void cascadeOneLevelDuringReplay(@Cascading Foo foo) { assert foo.getBar().doSomething() == 0; assert Foo.globalBar().doSomething() == 0; assert foo.getBar() != Foo.globalBar(); foo.doSomething("test"); assert foo.getIntValue() == 0; assert foo.getBooleanValue() == null; assert foo.getList().isEmpty(); } @Test public void verifyThatStaticMethodsAndConstructorsAreNotMockedWhenCascading(@Cascading Foo foo) { foo.getBar(); assert "notMocked".equals(Bar.staticMethod()); try { new Bar(); fail(); } catch (RuntimeException ignored) {} } @Test public void verifyThatStaticMethodsAndConstructorsAreMockedWhenCascadedMockIsMockedNormally( @Cascading Foo mockFoo, @Mocked Bar mockBar) { assert mockFoo.getBar() != mockBar; assert mockBar.doSomething() == 0; assert Bar.staticMethod() == null; new Bar(); } @Test public void cascadeOneLevelDuringRecord() { final List<Integer> list = Arrays.asList(1, 2, 3); new NonStrictExpectations() { @Cascading Foo foo; { foo.doSomething(anyString); minTimes = 2; foo.getBar().doSomething(); result = 2; Foo.globalBar().doSomething(); result = 3; foo.getBooleanValue(); result = true; foo.getIntValue(); result = -1; foo.getList(); result = list; } }; Foo foo = new Foo(); foo.doSomething("1"); assert foo.getBar().doSomething() == 2; foo.doSomething("2"); assert Foo.globalBar().doSomething() == 3; assert foo.getBooleanValue(); assert foo.getIntValue() == -1; assert list == foo.getList(); } @Test public void cascadeOneLevelDuringVerify(@Cascading final Foo foo) { Bar bar = foo.getBar(); bar.doSomething(); bar.doSomething(); Foo.globalBar().doSomething(); assert foo.getIntValue() == 0; assert foo.getBooleanValue() == null; assert foo.getList().isEmpty(); new Verifications() { { foo.getBar().doSomething(); minTimes = 3; } }; new VerificationsInOrder() { { foo.getIntValue(); foo.getBooleanValue(); } }; } @Test public void cascadeTwoLevelsDuringReplay(@Cascading Foo foo) { foo.getBar().getBaz().runIt(); } @Test public void cascadeTwoLevelsDuringRecord() { new Expectations() { @Cascading @Mocked final Foo foo = new Foo(); { foo.getBar().doSomething(); result = 1; Foo.globalBar().doSomething(); result = 2; foo.getBar().getBaz().runIt(); times = 2; } }; Foo foo = new Foo(); assert foo.getBar().doSomething() == 1; assert Foo.globalBar().doSomething() == 2; Baz baz = foo.getBar().getBaz(); baz.runIt(); baz.runIt(); } @Test public void cascadeTwoLevelsWithInvocationRecordedOnLastMockOnly(@Cascading Foo foo) { new Expectations() { Baz baz; { baz.runIt(); } }; // Intermediate mocked type Bar is never mentioned above. foo.getBar().getBaz().runIt(); } @Test public void cascadeTwoLevelsAndVerifyInvocationOnLastMockOnly(@Cascading Foo foo, final Baz baz) { foo.getBar().getBaz().runIt(); new Verifications() { { baz.runIt(); } }; } // Tests using the java.lang.Process and java.lang.ProcessBuilder classes ////////////////////////////////////////// @Test public void cascadeOnJREClasses() throws Exception { new NonStrictExpectations() { @Cascading ProcessBuilder pb; { ProcessBuilder sameBuilder = pb.directory((File) any); assert pb != sameBuilder; Process process = sameBuilder.start(); process.getOutputStream().write(5); process.exitValue(); result = 1; } }; Process process = new ProcessBuilder("test").directory(new File("myDir")).start(); process.getOutputStream().write(5); process.getOutputStream().flush(); assert process.exitValue() == 1; } // Tests using java.net classes //////////////////////////////////////////////////////////////////////////////////// static final class SocketFactory { public Socket createSocket() { return new Socket(); } public Socket createSocket(String host, int port) throws IOException { return new Socket(host, port); } } @Test public void mockThroughFinalMockFieldAClassToBeLaterMockedThroughCascading() { new NonStrictExpectations() { // This caused a NPE in later tests which cascade-mocked the Socket class: final Socket s = null; }; } @Test public void cascadeOneLevelWithArgumentMatchers(@Cascading final SocketFactory sf) throws Exception { new NonStrictExpectations() { { sf.createSocket(anyString, 80); result = null; } }; assert sf.createSocket("expected", 80) == null; assert sf.createSocket("unexpected", 8080) != null; } @Test public void recordAndVerifyOneLevelDeep(@Cascading final SocketFactory sf) throws Exception { final OutputStream out = new ByteArrayOutputStream(); new NonStrictExpectations() { { sf.createSocket().getOutputStream(); result = out; } }; assert out == sf.createSocket().getOutputStream(); new FullVerifications() { { sf.createSocket().getOutputStream(); } }; } @Test public void recordAndVerifyOnTwoCascadingMocksOfTheSameType( @Cascading final SocketFactory sf1, @Cascading final SocketFactory sf2) throws Exception { final OutputStream out1 = new ByteArrayOutputStream(); final OutputStream out2 = new ByteArrayOutputStream(); new NonStrictExpectations() { { sf1.createSocket().getOutputStream(); result = out1; sf2.createSocket().getOutputStream(); result = out2; } }; assert out1 == sf1.createSocket().getOutputStream(); assert out2 == sf2.createSocket().getOutputStream(); new FullVerificationsInOrder() { { sf1.createSocket().getOutputStream(); sf2.createSocket().getOutputStream(); } }; } @Test public void recordAndVerifySameInvocationOnMocksReturnedFromInvocationsWithDifferentArguments( @Cascading final SocketFactory sf) throws Exception { new NonStrictExpectations() { { sf.createSocket().getPort(); result = 1; sf.createSocket("first", 80).getPort(); result = 2; sf.createSocket("second", 80).getPort(); result = 3; sf.createSocket(anyString, 81).getPort(); result = 4; } }; assert sf.createSocket().getPort() == 1; assert sf.createSocket("first", 80).getPort() == 2; assert sf.createSocket("second", 80).getPort() == 3; assert sf.createSocket("third", 81).getPort() == 4; new Verifications() { { sf.createSocket("first", 80).getPort(); sf.createSocket().getPort(); times = 1; sf.createSocket(anyString, 81).getPort(); maxTimes = 1; sf.createSocket("second", 80).getPort(); sf.createSocket("fourth", -1); times = 0; } }; } @Test public void cascadeOnInheritedMethod(@Cascading SocketChannel sc) { assert sc.provider() != null; } @Test public void recordAndVerifyWithMixedCascadeLevels(@Cascading final SocketFactory sf) throws Exception { new NonStrictExpectations() { { sf.createSocket("first", 80).getKeepAlive(); result = true; sf.createSocket("second", anyInt).getChannel().close(); times = 1; } }; sf.createSocket("second", 80).getChannel().close(); assert sf.createSocket("first", 80).getKeepAlive(); sf.createSocket("first", 8080).getChannel().provider().openPipe(); new Verifications() { { sf.createSocket("first", 8080).getChannel().provider().openPipe(); } }; } @Test public void overrideCascadedMockAndRecordStrictExpectationOnIt(@Cascading final Foo foo, final Bar mockBar) { new Expectations() { { foo.getBar(); result = mockBar; mockBar.doSomething(); } }; Bar bar = foo.getBar(); bar.doSomething(); } @Test public void overrideCascadedMockAndRecordNonStrictExpectationOnIt(@Cascading final Foo foo) { new NonStrictExpectations() { Bar mockBar; { foo.getBar(); result = mockBar; mockBar.doSomething(); times = 1; result = 123; } }; Bar bar = foo.getBar(); assertEquals(123, bar.doSomething()); } @Test public void overrideTwoCascadedMocksOfTheSameType(@Cascading final Foo foo1, @Cascading final Foo foo2) { new Expectations() { Bar bar1; Bar bar2; { foo1.getBar(); result = bar1; foo2.getBar(); result = bar2; bar1.doSomething(); bar2.doSomething(); } }; Bar bar1 = foo1.getBar(); Bar bar2 = foo2.getBar(); bar1.doSomething(); bar2.doSomething(); } @Test(expected = AssertionError.class) public void overrideTwoCascadedMocksOfTheSameTypeButReplayInDifferentOrder( @Cascading final Foo foo1, @Cascading final Foo foo2) { new Expectations() { Bar bar1; Bar bar2; { foo1.getBar(); result = bar1; foo2.getBar(); result = bar2; bar1.doSomething(); bar2.doSomething(); } }; Bar bar1 = foo1.getBar(); Bar bar2 = foo2.getBar(); bar2.doSomething(); bar1.doSomething(); } @Test public void cascadedEnum(@Cascading final Foo mock) { new Expectations() { { mock.getBar().getEnum(); result = AnEnum.Second; } }; assertEquals(AnEnum.Second, mock.getBar().getEnum()); } @Test public void cascadedNonStrictEnumReturningConsecutiveValuesThroughResultField(@Cascading final Foo mock) { new NonStrictExpectations() { { mock.getBar().getEnum(); result = AnEnum.First; result = AnEnum.Second; result = AnEnum.Third; } }; assertSame(AnEnum.First, mock.getBar().getEnum()); assertSame(AnEnum.Second, mock.getBar().getEnum()); assertSame(AnEnum.Third, mock.getBar().getEnum()); } @Test public void cascadedNonStrictEnumReturningConsecutiveValuesThroughReturnsMethod(@NonStrict @Cascading final Foo mock) { new Expectations() { { mock.getBar().getEnum(); returns(AnEnum.First, AnEnum.Second, AnEnum.Third); } }; assertSame(AnEnum.First, mock.getBar().getEnum()); assertSame(AnEnum.Second, mock.getBar().getEnum()); assertSame(AnEnum.Third, mock.getBar().getEnum()); } @Test public void cascadedStrictEnumReturningConsecutiveValuesThroughResultField(@Cascading final Foo mock) { new Expectations() { { mock.getBar().getEnum(); result = AnEnum.Third; result = AnEnum.Second; result = AnEnum.First; } }; Bar bar = mock.getBar(); assertSame(AnEnum.Third, bar.getEnum()); assertSame(AnEnum.Second, bar.getEnum()); assertSame(AnEnum.First, bar.getEnum()); } @Test public void cascadedStrictEnumReturningConsecutiveValuesThroughReturnsMethod(@Cascading final Foo mock) { new Expectations() { { mock.getBar().getEnum(); returns(AnEnum.First, AnEnum.Second, AnEnum.Third); } }; Bar bar = mock.getBar(); assertSame(AnEnum.First, bar.getEnum()); assertSame(AnEnum.Second, bar.getEnum()); assertSame(AnEnum.Third, bar.getEnum()); } @Test public void overrideLastCascadedObjectWithNonMockedInstance() { final Date newDate = new Date(123); assertEquals(123, newDate.getTime()); new NonStrictExpectations() { @Cascading Foo foo; { foo.getBar().getBaz().getDate(); result = newDate; } }; assertSame(newDate, new Foo().getBar().getBaz().getDate()); assertEquals(123, newDate.getTime()); } @Test public void overrideLastCascadedObjectWithMockedInstance(final Date mockedDate) { Date newDate = new Date(123); assertEquals(0, newDate.getTime()); new NonStrictExpectations() { @Cascading Foo foo; { foo.getBar().getBaz().getDate(); result = mockedDate; } }; assertSame(mockedDate, new Foo().getBar().getBaz().getDate()); assertEquals(0, newDate.getTime()); assertEquals(0, mockedDate.getTime()); } @Test public void overrideLastCascadedObjectWithInjectableMockInstance(@Injectable final Date mockDate) { Date newDate = new Date(123); assertEquals(123, newDate.getTime()); new NonStrictExpectations() { @Cascading Foo foo; { foo.getBar().getBaz().getDate(); result = mockDate; } }; assertSame(mockDate, new Foo().getBar().getBaz().getDate()); assertEquals(123, newDate.getTime()); assertEquals(0, mockDate.getTime()); } }