package fitnesse.slim; 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 org.junit.Test; // 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; public interface Echo { public void echo(); public boolean echoCalled(); } public interface Speak { public void speak(); public boolean speakCalled(); } public interface Delete { public void delete(String fileName); public boolean deleteCalled(); } public interface SystemUnderTestFixture { public MySystemUnderTestBase getSystemUnderTest(); } public abstract static class MySystemUnderTestBase implements Speak, Echo { } public static abstract class MyAnnotatedSystemUnderTestFixture implements Echo, SystemUnderTestFixture { } public static abstract class FixtureWithNamedSystemUnderTestBase implements Echo, SystemUnderTestFixture { } public static abstract class SimpleFixture implements Echo { } public static abstract class EchoSupport implements Echo, Speak { } public static abstract class FileSupport implements Delete { } public abstract void init() throws Exception; @Test public void shouldCallMethodOnGivenInstanceBeforeTryingToInvokeOnSystemUnderTest() { MyAnnotatedSystemUnderTestFixture myInstance = createAnnotatedFixture(); Object result = statementExecutor.call(INSTANCE_NAME, echoMethodName()); assertEquals(voidMessage(), result); assertTrue(myInstance.echoCalled()); assertFalse(myInstance.getSystemUnderTest().speakCalled()); } @Test public void shouldCallMethodOnFieldAnnotatedWithSystemUnderTestWhenFixtureDoesNotHaveMethod() { MyAnnotatedSystemUnderTestFixture myFixture = createAnnotatedFixture(); executeStatementAndVerifyResultIsVoid(); assertFalse(myFixture.echoCalled()); assertTrue(myFixture.getSystemUnderTest().speakCalled()); } @Test public void shouldCallMethodOnFieldNamed_systemUnderTest_WhenFixtureDoesNotHaveMethod() { FixtureWithNamedSystemUnderTestBase myFixture = createNamedFixture(); executeStatementAndVerifyResultIsVoid(); assertFalse(myFixture.echoCalled()); assertTrue(myFixture.getSystemUnderTest().speakCalled()); } @Test public void shouldReportMissingMethodOnFixtureClassWhenMethodCanNotBeFoundOnBothFixtureAndSystemUnderTest() { createAnnotatedFixture(); String result = (String) statementExecutor.call(INSTANCE_NAME, "noSuchMethod"); String expectedErrorMessage = String.format(MESSAGE_NO_METHOD_IN_CLASS, "noSuchMethod", 0, annotatedFixtureName()); assertTrue(result.contains(expectedErrorMessage)); } @Test public void shouldPreferMethodOnFixtureOverMethodOnSystemUnderTest() { FixtureWithNamedSystemUnderTestBase instance = createNamedFixture(); statementExecutor.call(INSTANCE_NAME, echoMethodName()); assertFalse(instance.getSystemUnderTest().echoCalled()); assertTrue(instance.echoCalled()); } @Test public void shouldPreferMethodOnFixtureOverMethodOnLibrary() { SimpleFixture instance = createSimpleFixture(); EchoSupport echoLibrary = createEchoLibrary(); statementExecutor.call(INSTANCE_NAME, echoMethodName()); assertFalse(echoLibrary.echoCalled()); assertTrue(instance.echoCalled()); } @Test public void shouldPreferMethodOnSystemUnderTestOverMethodOnLibrary() { FixtureWithNamedSystemUnderTestBase instance = createNamedFixture(); EchoSupport echoLibrary = createEchoLibrary(); statementExecutor.call(INSTANCE_NAME, "speak"); assertFalse(echoLibrary.speakCalled()); assertTrue(instance.getSystemUnderTest().speakCalled()); } @Test public void shouldPreferMethodsOnLibrariesCreatedLaterOverMethodsOnLibrariesCreatedEarlier() { 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() { 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() { createFixtureInstance(echoLibraryName()); FileSupport library = createFileSupportLibrary(); assertNotNull(library); Object result = statementExecutor.call(INSTANCE_NAME, deleteMethodName(), "filename.txt"); assertEquals(voidMessage(), result); assertTrue(library.deleteCalled()); } protected MyAnnotatedSystemUnderTestFixture createAnnotatedFixture() { createFixtureInstance(annotatedFixtureName()); return (MyAnnotatedSystemUnderTestFixture) getVerifiedInstance(); } protected abstract String annotatedFixtureName(); protected FixtureWithNamedSystemUnderTestBase createNamedFixture() { createFixtureInstance(namedFixtureName()); return (FixtureWithNamedSystemUnderTestBase) getVerifiedInstance(); } protected abstract String namedFixtureName(); protected SimpleFixture createSimpleFixture() { createFixtureInstance(simpleFixtureName()); return (SimpleFixture) getVerifiedInstance(); } protected abstract String simpleFixtureName(); protected EchoSupport createEchoLibrary() { String instanceName = "library" + library++; statementExecutor.create(instanceName, echoLibraryName(), new Object[] {}); return (EchoSupport) statementExecutor.getInstance(instanceName); } protected abstract String echoLibraryName(); protected FileSupport createFileSupportLibrary() { String instanceName = "library" + library++; statementExecutor.create(instanceName, fileSupportName(), new Object[] {}); return (FileSupport) statementExecutor.getInstance(instanceName); } protected abstract String fileSupportName(); protected void createFixtureInstance(String fixtureClass) { Object created = statementExecutor.create(INSTANCE_NAME, fixtureClass, new Object[] {}); assertEquals("OK", created); } protected Echo getVerifiedInstance() { Echo myInstance = (Echo) statementExecutor.getInstance(INSTANCE_NAME); assertFalse(myInstance.echoCalled()); return myInstance; } protected void executeStatementAndVerifyResultIsVoid() { Object result = statementExecutor.call(INSTANCE_NAME, "speak"); assertEquals(voidMessage(), result); } }