package fitnesse.slim; import fitnesse.slim.test.ConstructorThrows; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; // Extracted Test class to be implemented by all Java based Slim ports // The tests for PhpSlim and JsSlim implement this class public abstract class StatementExecutorTestBase { protected static final String MESSAGE_NO_METHOD_IN_CLASS = "message:<<NO_METHOD_IN_CLASS %s[%d] %s.>>"; protected static final String INSTANCE_NAME = "myInstance"; protected StatementExecutorInterface statementExecutor; // some untyped languages do not explicitly define void return values protected String voidMessage() { return "/__VOID__/"; } // echo is a keyword in some languages, allow for other methodNames protected String echoMethodName() { return "echo"; } // delete is a keyword in some languages, allow for other methodNames protected String deleteMethodName() { return "delete"; } protected int library = 0; interface Echo { void echo(); boolean echoCalled(); } interface Speak { void speak(); boolean speakCalled(); } interface Delete { void delete(String fileName); boolean deleteCalled(); } interface SystemUnderTestFixture { MySystemUnderTestBase getSystemUnderTest(); } abstract static class MySystemUnderTestBase implements Speak, Echo { } abstract static class MyAnnotatedSystemUnderTestFixture implements Echo, SystemUnderTestFixture { } abstract static class FixtureWithNamedSystemUnderTestBase implements Echo, SystemUnderTestFixture { } abstract static class SimpleFixture implements Echo { } abstract static class EchoSupport implements Echo, Speak { } abstract static class FileSupport implements Delete { } public abstract void init() throws Exception; @Test public void shouldCallMethodOnGivenInstanceBeforeTryingToInvokeOnSystemUnderTest() throws Exception { MyAnnotatedSystemUnderTestFixture myInstance = createAnnotatedFixture(); Object result = statementExecutor.call(INSTANCE_NAME, echoMethodName()); assertEquals(voidMessage(), result); assertTrue(myInstance.echoCalled()); assertFalse(myInstance.getSystemUnderTest().speakCalled()); } @Test public void shouldCallMethodOnFieldAnnotatedWithSystemUnderTestWhenFixtureDoesNotHaveMethodAndMethodIsInSubclass() throws Exception { MyAnnotatedSystemUnderTestFixture myFixture = createAnnotatedFixture(); executeShoutStatementAndVerifyResultIsVoid(); assertFalse(myFixture.echoCalled()); assertTrue((((StatementExecutorTest.MySystemUnderTestJava)myFixture.getSystemUnderTest())).shoutCalled()); assertFalse(myFixture.getSystemUnderTest().speakCalled()); } @Test public void shouldCallMethodOnFieldAnnotatedWithSystemUnderTestWhenFixtureDoesNotHaveMethod() throws Exception { MyAnnotatedSystemUnderTestFixture myFixture = createAnnotatedFixture(); executeStatementAndVerifyResultIsVoid(); assertFalse(myFixture.echoCalled()); assertTrue(myFixture.getSystemUnderTest().speakCalled()); } @Test public void shouldCallMethodOnFieldNamed_systemUnderTest_WhenFixtureDoesNotHaveMethod() throws Exception { FixtureWithNamedSystemUnderTestBase myFixture = createNamedFixture(); executeStatementAndVerifyResultIsVoid(); assertFalse(myFixture.echoCalled()); assertTrue(myFixture.getSystemUnderTest().speakCalled()); } @Test public void shouldReportMissingMethodOnFixtureClassWhenMethodCanNotBeFoundOnBothFixtureAndSystemUnderTest() throws Exception { createAnnotatedFixture(); try { statementExecutor.call(INSTANCE_NAME, "noSuchMethod"); fail("Executed non-existing method."); } catch (SlimException e) { String expectedErrorMessage = String.format(MESSAGE_NO_METHOD_IN_CLASS, "noSuchMethod", 0, annotatedFixtureName()); assertTrue(e.getMessage(), e.getMessage().contains(expectedErrorMessage)); } } @Test public void shouldPreferMethodOnFixtureOverMethodOnSystemUnderTest() throws Exception { FixtureWithNamedSystemUnderTestBase instance = createNamedFixture(); statementExecutor.call(INSTANCE_NAME, echoMethodName()); assertFalse(instance.getSystemUnderTest().echoCalled()); assertTrue(instance.echoCalled()); } @Test public void shouldPreferMethodOnFixtureOverMethodOnLibrary() throws Exception { SimpleFixture instance = createSimpleFixture(); EchoSupport echoLibrary = createEchoLibrary(); statementExecutor.call(INSTANCE_NAME, echoMethodName()); assertFalse(echoLibrary.echoCalled()); assertTrue(instance.echoCalled()); } @Test public void shouldPreferMethodOnSystemUnderTestOverMethodOnLibrary() throws Exception { FixtureWithNamedSystemUnderTestBase instance = createNamedFixture(); EchoSupport echoLibrary = createEchoLibrary(); statementExecutor.call(INSTANCE_NAME, "speak"); assertFalse(echoLibrary.speakCalled()); assertTrue(instance.getSystemUnderTest().speakCalled()); } @Test public void shouldPreferMethodsOnLibrariesCreatedLaterOverMethodsOnLibrariesCreatedEarlier() throws Exception { createSimpleFixture(); EchoSupport echoLibrary1 = createEchoLibrary(); EchoSupport echoLibrary2 = createEchoLibrary(); EchoSupport echoLibrary3 = createEchoLibrary(); statementExecutor.call(INSTANCE_NAME, "speak"); assertFalse(echoLibrary1.speakCalled()); assertFalse(echoLibrary2.speakCalled()); assertTrue(echoLibrary3.speakCalled()); } @Test public void shouldCallMethodOnInstallLibraryWhenMethodIsNotFoundInAFixture_WithSystemUnderTestInFixture() throws Exception { createNamedFixture(); FileSupport library = createFileSupportLibrary(); assertNotNull(library); Object result = statementExecutor.call(INSTANCE_NAME, deleteMethodName(), "filename.txt"); assertEquals(voidMessage(), result); assertTrue(library.deleteCalled()); } @Test public void shouldCallMethodOnInstallLibraryWhenMethodIsNotFoundInAFixture() throws Exception { createFixtureInstance(echoLibraryName()); FileSupport library = createFileSupportLibrary(); assertNotNull(library); Object result = statementExecutor.call(INSTANCE_NAME, deleteMethodName(), "filename.txt"); assertEquals(voidMessage(), result); assertTrue(library.deleteCalled()); } @Test public void shouldThrowStopTestExceptionFromConstructor() { try { statementExecutor.create(INSTANCE_NAME, ConstructorThrows.class.getCanonicalName(), new Object[] { "stop test" }); } catch (SlimException e) { assertTrue(e.toString(), e.toString().startsWith(SlimServer.EXCEPTION_STOP_TEST_TAG)); assertTrue(statementExecutor.stopHasBeenRequested()); return; } fail("should not get here"); } protected MyAnnotatedSystemUnderTestFixture createAnnotatedFixture() throws Exception { createFixtureInstance(annotatedFixtureName()); return (MyAnnotatedSystemUnderTestFixture) getVerifiedInstance(); } protected abstract String annotatedFixtureName(); protected FixtureWithNamedSystemUnderTestBase createNamedFixture() throws Exception { createFixtureInstance(namedFixtureName()); return (FixtureWithNamedSystemUnderTestBase) getVerifiedInstance(); } protected abstract String namedFixtureName(); protected SimpleFixture createSimpleFixture() throws Exception { createFixtureInstance(simpleFixtureName()); return (SimpleFixture) getVerifiedInstance(); } protected abstract String simpleFixtureName(); protected EchoSupport createEchoLibrary() throws Exception { String instanceName = "library" + library++; statementExecutor.create(instanceName, echoLibraryName(), new Object[] {}); return (EchoSupport) statementExecutor.getInstance(instanceName); } protected abstract String echoLibraryName(); protected FileSupport createFileSupportLibrary() throws Exception { String instanceName = "library" + library++; statementExecutor.create(instanceName, fileSupportName(), new Object[] {}); return (FileSupport) statementExecutor.getInstance(instanceName); } protected abstract String fileSupportName(); protected void createFixtureInstance(String fixtureClass) throws Exception { statementExecutor.create(INSTANCE_NAME, fixtureClass, new Object[] {}); } protected Echo getVerifiedInstance() { Echo myInstance = (Echo) statementExecutor.getInstance(INSTANCE_NAME); assertFalse(myInstance.echoCalled()); return myInstance; } protected void executeStatementAndVerifyResultIsVoid() throws Exception { Object result = statementExecutor.call(INSTANCE_NAME, "speak"); assertEquals(voidMessage(), result); } protected void executeShoutStatementAndVerifyResultIsVoid() throws Exception { Object result = statementExecutor.call(INSTANCE_NAME, "shout"); assertEquals(voidMessage(), result); } }