From ac6c415dce1263abec235084dd8d3975ed9c21cb Mon Sep 17 00:00:00 2001 From: Caner Date: Thu, 28 Jun 2012 16:56:01 +0100 Subject: [PATCH] rs-mock --- .../main/java/play/baseline/model/Pet.java | 36 ++++++- .../baseline/util/SimpleHttpExporter.java | 1 + .../src/main/resources/applicationContext.xml | 15 +-- .../src/main/resources/dao-context.xml | 19 ++++ .../src/main/resources/log4j.properties | 10 ++ .../test/java/remotemock/IntegrationTest.java | 76 +++++++++++++++ .../src/test/java/remotemock/TestMock.java | 27 ------ .../test/java/remotemock}/UnitTestPetDao.java | 26 ++--- baseline/stub-service/pom.xml | 5 + .../java/play/baseline/stub/MockDatabase.java | 23 +++++ .../play/baseline/stub/MockDatabaseImpl.java | 28 ++++++ .../java/play/baseline/stub/QueryResult.java | 13 +++ .../play/baseline/stub/StubMyServiceImpl.java | 34 ------- .../play/baseline/stub/StubPetDaoImpl.java | 36 +++++++ .../src/main/resources/applicationContext.xml | 9 +- .../it/MockTest_UptoDaoInterface.java | 92 ++++++++++++++++++ .../it/MockTest_UptoJdbcInterfaces.java | 97 +++++++++++++++++++ .../test/java/remotemock/it/RemoteTest.java | 55 ----------- .../test/resources/test-applicationConfig.xml | 5 - pom.xml | 19 ++++ .../processor/RemotableInvocationHandler.java | 5 + .../java/play/remotemock/util/ClassUtil.java | 36 +++++++ .../remotemock/util/RemotableMockFactory.java | 9 +- resultsetmock/pom.xml | 17 ++-- .../resultsetmock/jdbc/MockJdbcFactory.java | 37 ++++++- .../test/java/play/resultsetmock/IModel.java | 10 -- .../test/java/play/resultsetmock/Model.java | 26 ----- .../resultsetmock/jdbc/ComponentTest.java | 35 ------- .../java/play/resultsetmock/jdbc/Test.java | 97 ------------------- 29 files changed, 558 insertions(+), 340 deletions(-) create mode 100644 baseline/service/src/main/resources/dao-context.xml create mode 100644 baseline/service/src/main/resources/log4j.properties create mode 100644 baseline/service/src/test/java/remotemock/IntegrationTest.java delete mode 100644 baseline/service/src/test/java/remotemock/TestMock.java rename {resultsetmock/src/test/java/play/resultsetmock/jdbc => baseline/service/src/test/java/remotemock}/UnitTestPetDao.java (70%) create mode 100644 baseline/stub-service/src/main/java/play/baseline/stub/MockDatabase.java create mode 100644 baseline/stub-service/src/main/java/play/baseline/stub/MockDatabaseImpl.java create mode 100644 baseline/stub-service/src/main/java/play/baseline/stub/QueryResult.java delete mode 100644 baseline/stub-service/src/main/java/play/baseline/stub/StubMyServiceImpl.java create mode 100644 baseline/stub-service/src/main/java/play/baseline/stub/StubPetDaoImpl.java create mode 100644 baseline/tests/src/test/java/remotemock/it/MockTest_UptoDaoInterface.java create mode 100644 baseline/tests/src/test/java/remotemock/it/MockTest_UptoJdbcInterfaces.java delete mode 100644 baseline/tests/src/test/java/remotemock/it/RemoteTest.java create mode 100644 remotemock/src/main/java/play/remotemock/util/ClassUtil.java delete mode 100644 resultsetmock/src/test/java/play/resultsetmock/IModel.java delete mode 100644 resultsetmock/src/test/java/play/resultsetmock/Model.java delete mode 100644 resultsetmock/src/test/java/play/resultsetmock/jdbc/ComponentTest.java delete mode 100644 resultsetmock/src/test/java/play/resultsetmock/jdbc/Test.java diff --git a/baseline/service/src/main/java/play/baseline/model/Pet.java b/baseline/service/src/main/java/play/baseline/model/Pet.java index b403bb6..2d753a7 100644 --- a/baseline/service/src/main/java/play/baseline/model/Pet.java +++ b/baseline/service/src/main/java/play/baseline/model/Pet.java @@ -1,14 +1,16 @@ package play.baseline.model; -public class Pet { +import java.io.Serializable; + +public class Pet implements Serializable { - int id; + private int id; - String name; + private String name; - int age; + private int age; - String owner; + private String owner; public Pet() { } @@ -44,4 +46,28 @@ public String getOwner() { public void setOwner(String owner) { this.owner = owner; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Pet pet = (Pet) o; + + if (age != pet.age) return false; + if (id != pet.id) return false; + if (name != null ? !name.equals(pet.name) : pet.name != null) return false; + if (owner != null ? !owner.equals(pet.owner) : pet.owner != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = id; + result = 31 * result + (name != null ? name.hashCode() : 0); + result = 31 * result + age; + result = 31 * result + (owner != null ? owner.hashCode() : 0); + return result; + } } diff --git a/baseline/service/src/main/java/play/baseline/util/SimpleHttpExporter.java b/baseline/service/src/main/java/play/baseline/util/SimpleHttpExporter.java index 5fabcec..13a727e 100644 --- a/baseline/service/src/main/java/play/baseline/util/SimpleHttpExporter.java +++ b/baseline/service/src/main/java/play/baseline/util/SimpleHttpExporter.java @@ -77,6 +77,7 @@ private Callable getExecutableByUri(final URI requestURI) { return new Callable() { @Override public Object call() throws Exception { + System.out.println("method = " + getArgs(method, requestURI.getPath())[0]); return method.invoke(service, getArgs(method, requestURI.getPath())); } }; diff --git a/baseline/service/src/main/resources/applicationContext.xml b/baseline/service/src/main/resources/applicationContext.xml index 79b546d..ab02a10 100644 --- a/baseline/service/src/main/resources/applicationContext.xml +++ b/baseline/service/src/main/resources/applicationContext.xml @@ -7,20 +7,13 @@ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd"> + + - - - - - - - - - - @@ -30,7 +23,7 @@ class="org.springframework.remoting.support.SimpleHttpServerFactoryBean"> - + diff --git a/baseline/service/src/main/resources/dao-context.xml b/baseline/service/src/main/resources/dao-context.xml new file mode 100644 index 0000000..1bf7bef --- /dev/null +++ b/baseline/service/src/main/resources/dao-context.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/baseline/service/src/main/resources/log4j.properties b/baseline/service/src/main/resources/log4j.properties new file mode 100644 index 0000000..ae561bc --- /dev/null +++ b/baseline/service/src/main/resources/log4j.properties @@ -0,0 +1,10 @@ +# Set root logger level to DEBUG and its only appender to A1. +log4j.rootLogger=DEBUG, A1 +log4j.logger.org.springframework=INFO + +# A1 is set to be a ConsoleAppender. +log4j.appender.A1=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n \ No newline at end of file diff --git a/baseline/service/src/test/java/remotemock/IntegrationTest.java b/baseline/service/src/test/java/remotemock/IntegrationTest.java new file mode 100644 index 0000000..c0a78a9 --- /dev/null +++ b/baseline/service/src/test/java/remotemock/IntegrationTest.java @@ -0,0 +1,76 @@ +package remotemock; + +import com.google.common.collect.Lists; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mock; +import org.springframework.util.AntPathMatcher; +import play.baseline.BaselineService; +import play.baseline.Main; +import play.baseline.model.Pet; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.mockito.Mockito.doReturn; + +/** + * Run server. (with database) + * Make a call & check result + */ +public class IntegrationTest { + + private static String PATH_QUERY_BY_NAME = "/pets/list/name={name}&age={age}"; + + private static Process server; + + @BeforeClass + public static void startServer() throws IOException, InterruptedException { + String classpath = System.getProperty("java.class.path"); + String className = Main.class.getCanonicalName(); + ProcessBuilder pb = new ProcessBuilder("java", "-cp", classpath, className, "-Dlog4j.debug=true"); + pb.inheritIO(); + server = pb.start(); + Thread.sleep(5000); + } + + @org.junit.Test + public void testListByNameAndAge() throws InterruptedException, IOException { + String query = PATH_QUERY_BY_NAME.replace("{name}", "Cango").replace("{age}", "3"); + String response = getResponse(query); + + ObjectMapper mapper = new ObjectMapper(); + List pets = mapper.readValue(response, new TypeReference>() { + }); + + Pet pet = new Pet(); + pet.setId(1); + pet.setName("Cango"); + pet.setAge(3); + pet.setOwner("Osman Bosman"); + List exptected = Lists.newArrayList(pet); + + Assert.assertEquals("Invalid return value", exptected, pets); + } + + @AfterClass + public static void stopServer() throws IOException { + server.destroy(); + } + + private String getResponse(String path) throws IOException { + URL url = new URL("http://localhost:8118" + path); + BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); + return reader.readLine(); + } + +} diff --git a/baseline/service/src/test/java/remotemock/TestMock.java b/baseline/service/src/test/java/remotemock/TestMock.java deleted file mode 100644 index 6c023df..0000000 --- a/baseline/service/src/test/java/remotemock/TestMock.java +++ /dev/null @@ -1,27 +0,0 @@ -package remotemock; - -import org.junit.Test; -import org.mockito.Mock; -import org.springframework.util.AntPathMatcher; -import play.baseline.BaselineService; - -import java.util.Map; - -public class TestMock { - - @Mock - BaselineService mockService; - - @Test - public void replace() { - } - - - @Test - public void tt() { - String ptr = "/spring-web/name={name}&age={age}"; - AntPathMatcher matcher = new AntPathMatcher(); - Map stringStringMap = matcher.extractUriTemplateVariables(ptr, "/spring-web/name=caner&age=32"); - System.out.println("stringStringMap = " + stringStringMap); - } -} diff --git a/resultsetmock/src/test/java/play/resultsetmock/jdbc/UnitTestPetDao.java b/baseline/service/src/test/java/remotemock/UnitTestPetDao.java similarity index 70% rename from resultsetmock/src/test/java/play/resultsetmock/jdbc/UnitTestPetDao.java rename to baseline/service/src/test/java/remotemock/UnitTestPetDao.java index 193d910..246eae2 100644 --- a/resultsetmock/src/test/java/play/resultsetmock/jdbc/UnitTestPetDao.java +++ b/baseline/service/src/test/java/remotemock/UnitTestPetDao.java @@ -1,6 +1,9 @@ -package play.resultsetmock.jdbc; +package remotemock; import org.junit.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; import play.baseline.dao.PetDao; import play.baseline.dao.PetDaoImpl; import play.baseline.model.Pet; @@ -11,25 +14,16 @@ import java.util.List; /** - * Assume db contains; - * - * - * - * - * - * - *
nameageowner_firstnameowner_lastname
Cango3OsmanBosman
Koko8HakanTarkan
Toto9OsmanBosman
- * - * The aim is to make this test pass using different DataSources + * Use actual db. */ public class UnitTestPetDao { - DataSource dataSource; // injected + private static PetDao petDao; // class under test - private PetDao petDao; // class under test - - public void init() { - petDao = new PetDaoImpl(dataSource); + @BeforeClass + public static void setup() { + ApplicationContext context = new ClassPathXmlApplicationContext("dao-context.xml"); + petDao = (PetDao) context.getBean("petDao"); } @org.junit.Test diff --git a/baseline/stub-service/pom.xml b/baseline/stub-service/pom.xml index 36636d5..fb72c57 100644 --- a/baseline/stub-service/pom.xml +++ b/baseline/stub-service/pom.xml @@ -29,5 +29,10 @@ remotemock ${project.version} + + ccaner.play + resultsetmock + ${project.version} + \ No newline at end of file diff --git a/baseline/stub-service/src/main/java/play/baseline/stub/MockDatabase.java b/baseline/stub-service/src/main/java/play/baseline/stub/MockDatabase.java new file mode 100644 index 0000000..7978269 --- /dev/null +++ b/baseline/stub-service/src/main/java/play/baseline/stub/MockDatabase.java @@ -0,0 +1,23 @@ +package play.baseline.stub; + +import play.resultsetmock.annotations.Param; +import play.resultsetmock.annotations.Query; + +/** + * With this interface we map sql queries, updates, calls to Java methods. + */ +public interface MockDatabase { + + @Query("select * from pets where name = ? and age = ?") + public QueryResult queryPetsTable( + @Param("name") String name, + @Param("age") int age); + +/* + @Query("select * from pets where owner_firstname = ?") + public QueryResult queryPetsTable( + @Param("owner_firstname") String ownerFirstName); +*/ + + +} diff --git a/baseline/stub-service/src/main/java/play/baseline/stub/MockDatabaseImpl.java b/baseline/stub-service/src/main/java/play/baseline/stub/MockDatabaseImpl.java new file mode 100644 index 0000000..4cb4696 --- /dev/null +++ b/baseline/stub-service/src/main/java/play/baseline/stub/MockDatabaseImpl.java @@ -0,0 +1,28 @@ +package play.baseline.stub; + +import play.baseline.model.Pet; +import play.remotemock.annotation.Remotable; +import play.resultsetmock.annotations.Param; +import play.resultsetmock.annotations.Query; + +import java.util.List; + +/** + * Default responses for sql calls, updates, queries... So that stub server starts up without errors. + */ +@Remotable(MockDatabase.class) +public class MockDatabaseImpl implements MockDatabase { + + @Override + public QueryResult queryPetsTable(String name, int age) { + return null; + } + +/* + @Override + public QueryResult queryPetsTable(String ownerFirstName) { + return null; + } +*/ + +} diff --git a/baseline/stub-service/src/main/java/play/baseline/stub/QueryResult.java b/baseline/stub-service/src/main/java/play/baseline/stub/QueryResult.java new file mode 100644 index 0000000..86ea0ee --- /dev/null +++ b/baseline/stub-service/src/main/java/play/baseline/stub/QueryResult.java @@ -0,0 +1,13 @@ +package play.baseline.stub; + +import java.io.Serializable; + +/** + * Created by IntelliJ IDEA. + * User: akpinarc + * Date: 6/28/12 + * Time: 2:02 PM + * To change this template use File | Settings | File Templates. + */ +public interface QueryResult extends Serializable { +} diff --git a/baseline/stub-service/src/main/java/play/baseline/stub/StubMyServiceImpl.java b/baseline/stub-service/src/main/java/play/baseline/stub/StubMyServiceImpl.java deleted file mode 100644 index 9c8f142..0000000 --- a/baseline/stub-service/src/main/java/play/baseline/stub/StubMyServiceImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package play.baseline.stub; - -import org.springframework.web.bind.annotation.PathVariable; -import play.baseline.BaselineService; -import play.baseline.model.Pet; -import play.remotemock.annotation.Remotable; - -import java.util.ArrayList; -import java.util.List; - -@Remotable(BaselineService.class) -public class StubMyServiceImpl implements BaselineService { - - @Override - public List listPets(String name, int age) { - return new ArrayList(); - } - - @Override - public List listPets(String ownerFirstName) { - return new ArrayList(); - } - - @Override - public String returnSomething() { - return "Stub: do something"; - } - - @Override - public String returnSomethingElse() { - return "Stub: do something else"; - } - -} diff --git a/baseline/stub-service/src/main/java/play/baseline/stub/StubPetDaoImpl.java b/baseline/stub-service/src/main/java/play/baseline/stub/StubPetDaoImpl.java new file mode 100644 index 0000000..6f457bd --- /dev/null +++ b/baseline/stub-service/src/main/java/play/baseline/stub/StubPetDaoImpl.java @@ -0,0 +1,36 @@ +package play.baseline.stub; + +import com.google.common.collect.Lists; +import org.springframework.web.bind.annotation.PathVariable; +import play.baseline.BaselineService; +import play.baseline.dao.PetDao; +import play.baseline.model.Pet; +import play.remotemock.annotation.Remotable; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +@Remotable(PetDao.class) +public class StubPetDaoImpl implements PetDao { + + @Override + public List loadPets(String name, int age) { + Pet p1 = new Pet(); + p1.setId(10); + p1.setName(name); + p1.setAge(age); + p1.setOwner("Mock Osman"); + return Lists.newArrayList(p1); + } + + @Override + public List loadPets(String ownerFirstName) { + Pet p1 = new Pet(); + p1.setId(10); + p1.setName("MockPet"); + p1.setAge(11); + p1.setOwner(ownerFirstName + " Bosman"); + return Lists.newArrayList(p1); + } +} diff --git a/baseline/stub-service/src/main/resources/applicationContext.xml b/baseline/stub-service/src/main/resources/applicationContext.xml index 43cf9a8..0ef8b30 100644 --- a/baseline/stub-service/src/main/resources/applicationContext.xml +++ b/baseline/stub-service/src/main/resources/applicationContext.xml @@ -17,7 +17,12 @@
- - + + + + + + + \ No newline at end of file diff --git a/baseline/tests/src/test/java/remotemock/it/MockTest_UptoDaoInterface.java b/baseline/tests/src/test/java/remotemock/it/MockTest_UptoDaoInterface.java new file mode 100644 index 0000000..6fee236 --- /dev/null +++ b/baseline/tests/src/test/java/remotemock/it/MockTest_UptoDaoInterface.java @@ -0,0 +1,92 @@ +package remotemock.it; + +import com.google.common.collect.Lists; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import play.baseline.BaselineService; +import play.baseline.Main; +import play.baseline.dao.PetDao; +import play.baseline.model.Pet; +import play.remotemock.util.RemotableMockFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLEncoder; +import java.util.List; + +import static org.mockito.Mockito.*; + +/** + * Test everything up to Dao interface on a running server. + * This excludes dao impl (possible resultset mappers etc) and actual SQLs (only possible to test if an actual DB exists) + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:test-applicationConfig.xml") +public class MockTest_UptoDaoInterface { + + @Autowired + RemotableMockFactory mockFactory; + + private static final String PATH_QUERY_BY_OWNER = "/pets/list/ownerFirstName={ownerFirstName}"; + + private static Process server; + + @BeforeClass + public static void startServer() throws IOException, InterruptedException { + String classpath = System.getProperty("java.class.path"); + String javaHome = System.getProperty("java.home"); + String javaBin = javaHome + + File.separator + "bin" + + File.separator + "java"; + String className = Main.class.getCanonicalName(); + ProcessBuilder pb = new ProcessBuilder(javaBin, "-cp", classpath, className); + pb.inheritIO(); + server = pb.start(); + Thread.sleep(5000); + } + + + @Test + public void testFindPetByOwnerName() throws Exception { + PetDao mockPetDao = mockFactory.mockAndAttach(PetDao.class, "PetDao"); + Pet p = new Pet(); + p.setId(55); + p.setName("MockPet"); + p.setAge(43); + p.setOwner("Osman Bosman"); + doReturn(Lists.newArrayList(p)).when(mockPetDao).loadPets(eq("Osman Bosman")); + + String query = PATH_QUERY_BY_OWNER.replace("{ownerFirstName}", "Osman Bosman"); + String response = getResponse(query); + + ObjectMapper mapper = new ObjectMapper(); + List pets = mapper.readValue(response, new TypeReference>() {}); + + Assert.assertEquals("Invalid return value", Lists.newArrayList(p), pets); + + verify(mockPetDao, times(1)).loadPets(eq("Osman Bosman")); + } + + private String getResponse(String path) throws IOException { + URL url = new URL("http://localhost:8118" + path.replace(" ", "%20")); + BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); + return reader.readLine(); + } + + @AfterClass + public static void stopServer() throws IOException, InterruptedException { + server.destroy(); + } + +} diff --git a/baseline/tests/src/test/java/remotemock/it/MockTest_UptoJdbcInterfaces.java b/baseline/tests/src/test/java/remotemock/it/MockTest_UptoJdbcInterfaces.java new file mode 100644 index 0000000..26f6195 --- /dev/null +++ b/baseline/tests/src/test/java/remotemock/it/MockTest_UptoJdbcInterfaces.java @@ -0,0 +1,97 @@ +package remotemock.it; + +import com.google.common.collect.Lists; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import play.baseline.Main; +import play.baseline.dao.PetDao; +import play.baseline.model.Pet; +import play.baseline.stub.MockDatabase; +import play.baseline.stub.QueryResult; +import play.remotemock.util.RemotableMockFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.List; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * Test everything up to Jdbc interfaces on a running server. + * This excludes actual SQLs (only possible to test if an actual DB exists) + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:test-applicationConfig.xml") +public class MockTest_UptoJdbcInterfaces { + + @Autowired + RemotableMockFactory mockFactory; + + private static final String PATH_QUERY_BY_NAME = "/pets/list/name={name}&age={age}"; + + private static Process server; + + @BeforeClass + public static void startServer() throws IOException, InterruptedException { + String classpath = System.getProperty("java.class.path"); + String javaHome = System.getProperty("java.home"); + String javaBin = javaHome + + File.separator + "bin" + + File.separator + "java"; + String className = Main.class.getCanonicalName(); + ProcessBuilder pb = new ProcessBuilder(javaBin, "-cp", classpath, className); + pb.inheritIO(); + server = pb.start(); + Thread.sleep(5000); + } + + + @Test + public void testFindPetByNameAndAge() throws Exception { + MockDatabase mockDatabase = mockFactory.mockAndAttach(MockDatabase.class, "MockDatabase"); + + doReturn(new QueryResult() {}).when(mockDatabase).queryPetsTable(eq("Cango"), 33); + + + String query = PATH_QUERY_BY_NAME.replace("{name}", "Cango").replace("age", "33"); + String response = getResponse(query); + + ObjectMapper mapper = new ObjectMapper(); + List pets = mapper.readValue(response, new TypeReference>() {}); + + Pet p = new Pet(); + p.setId(55); + p.setName("Cango"); + p.setAge(33); + p.setOwner("Osman Bosman"); + Assert.assertEquals("Invalid return value", Lists.newArrayList(p), pets); + + verify(mockDatabase, times(1)).queryPetsTable(eq("Cango"), 33); + } + + private String getResponse(String path) throws IOException { + URL url = new URL("http://localhost:8118" + path.replace(" ", "%20")); + BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); + return reader.readLine(); + } + + @AfterClass + public static void stopServer() throws IOException, InterruptedException { + server.destroy(); + } + +} diff --git a/baseline/tests/src/test/java/remotemock/it/RemoteTest.java b/baseline/tests/src/test/java/remotemock/it/RemoteTest.java deleted file mode 100644 index 8485324..0000000 --- a/baseline/tests/src/test/java/remotemock/it/RemoteTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package remotemock.it; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import play.baseline.BaselineService; -import play.remotemock.util.RemotableMockFactory; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; - -import static org.mockito.Mockito.*; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("classpath:test-applicationConfig.xml") -public class RemoteTest { - - @Autowired - RemotableMockFactory mockFactory; - - @Test - public void testStubCall() throws Exception { - String response = getResponse("/doSomething"); - Assert.assertEquals("Stub message expected", "Stub: do something", response); - } - - @Test - public void testMock() throws Exception { - BaselineService myServiceMock = mockFactory.mockAndAttach(BaselineService.class, "BaselineService"); - doReturn("Mocked response").when(myServiceMock).returnSomething(); - - String response = getResponse("/doSomething"); - Assert.assertEquals("Mocked message expected", "Mocked response", response); - - verify(myServiceMock, times(1)).returnSomething(); - - response = getResponse("/doSomethingElse"); - Assert.assertEquals("Stub message expected", "Stub: do something else", response); - - verify(myServiceMock, times(1)).returnSomethingElse(); - } - - private String getResponse(String path) throws IOException { - URL url = new URL("http://localhost:8118/BaselineService" + path); - BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); - return reader.readLine(); - } - - -} diff --git a/baseline/tests/src/test/resources/test-applicationConfig.xml b/baseline/tests/src/test/resources/test-applicationConfig.xml index 7e957a9..618f991 100644 --- a/baseline/tests/src/test/resources/test-applicationConfig.xml +++ b/baseline/tests/src/test/resources/test-applicationConfig.xml @@ -17,9 +17,4 @@ - - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index 65ed8a2..9b622b9 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,7 @@ 1.6.4 2.2.8 1.9.7 + 12.0 @@ -116,6 +117,16 @@ jackson-mapper-asl ${jackson.version} + + com.google.guava + guava + ${guava.version} + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + @@ -164,10 +175,18 @@ org.slf4j slf4j-api + + org.slf4j + slf4j-log4j12 + org.hsqldb hsqldb + + com.google.guava + guava + diff --git a/remotemock/src/main/java/play/remotemock/processor/RemotableInvocationHandler.java b/remotemock/src/main/java/play/remotemock/processor/RemotableInvocationHandler.java index 0dbc2ae..b69dfca 100644 --- a/remotemock/src/main/java/play/remotemock/processor/RemotableInvocationHandler.java +++ b/remotemock/src/main/java/play/remotemock/processor/RemotableInvocationHandler.java @@ -43,12 +43,17 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl logRemote(method, args, result); return result; } catch (InvocationTargetException e) { + System.out.println("e = " + e.getCause()); + System.out.println("e5 = " + e.getCause().getCause()); if (InvokeLocalMethodException.class.isInstance(e.getCause())) { + System.out.println("e2 = " + e); Object result = method.invoke(helper.localObject, args); logRedirect(method, args, result); return result; } throw e.getCause(); + } catch (Exception e) { + System.out.println("e3 = " + e); } } Object result = method.invoke(helper.localObject, args); diff --git a/remotemock/src/main/java/play/remotemock/util/ClassUtil.java b/remotemock/src/main/java/play/remotemock/util/ClassUtil.java new file mode 100644 index 0000000..811a7e3 --- /dev/null +++ b/remotemock/src/main/java/play/remotemock/util/ClassUtil.java @@ -0,0 +1,36 @@ +package play.remotemock.util; + +import org.mockito.asm.Type; +import org.mockito.cglib.core.Signature; +import org.mockito.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; + +public class ClassUtil { + + public static Class getDeclaringClass(Object object, Method method) { + try { + Method overridden = object.getClass().getMethod(method.getName(), method.getParameterTypes()); + return overridden.getDeclaringClass(); + } catch (NoSuchMethodException e) { + return method.getDeclaringClass(); + } + } + + public static boolean declaresMethod(Class clazz, Method method) { + try { + clazz.getMethod(method.getName(), method.getParameterTypes()); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } + + public static Object invokeMethodOnProxy(Object proxy, Method method, Object[] args) throws Throwable { + MethodProxy methodProxy = MethodProxy.find(proxy.getClass(), new Signature(method.getName(), + Type.getReturnType(method), + Type.getArgumentTypes(method))); + return methodProxy.invokeSuper(proxy, args); + } + +} diff --git a/remotemock/src/main/java/play/remotemock/util/RemotableMockFactory.java b/remotemock/src/main/java/play/remotemock/util/RemotableMockFactory.java index fee1bce..25cea42 100644 --- a/remotemock/src/main/java/play/remotemock/util/RemotableMockFactory.java +++ b/remotemock/src/main/java/play/remotemock/util/RemotableMockFactory.java @@ -60,11 +60,12 @@ static class RemotableMockAnswer implements Answer { @Override public Object answer(InvocationOnMock invocation) throws Throwable { /* mockito passes toString calls to default answer */ -// if (ClassUtils.declaresMethod(serviceInterface, invocation.getMethod())) { + if (ClassUtil.declaresMethod(serviceInterface, invocation.getMethod())) { + System.out.println("invocation = " + invocation); throw new InvokeLocalMethodException(); -// } -// return ClassUtil.invokeMethodOnProxy(invocation.getMock(), -// invocation.getMethod(), invocation.getArguments()); + } + return ClassUtil.invokeMethodOnProxy(invocation.getMock(), + invocation.getMethod(), invocation.getArguments()); } } diff --git a/resultsetmock/pom.xml b/resultsetmock/pom.xml index 5a3c19e..50065f5 100644 --- a/resultsetmock/pom.xml +++ b/resultsetmock/pom.xml @@ -15,21 +15,18 @@ jar - - com.google.collections - google-collections - 1.0 - - - com.google.guava - guava - 11.0.2 - ccaner.play.remotemock service ${project.version} + + org.mockito + mockito-core + ${mockito.version} + compile + + diff --git a/resultsetmock/src/main/java/play/resultsetmock/jdbc/MockJdbcFactory.java b/resultsetmock/src/main/java/play/resultsetmock/jdbc/MockJdbcFactory.java index 14ce1e7..a83812d 100644 --- a/resultsetmock/src/main/java/play/resultsetmock/jdbc/MockJdbcFactory.java +++ b/resultsetmock/src/main/java/play/resultsetmock/jdbc/MockJdbcFactory.java @@ -1,25 +1,56 @@ package play.resultsetmock.jdbc; import com.google.common.base.Defaults; +import org.mockito.Mock; +import org.mockito.Mockito; import javax.sql.DataSource; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.sql.ResultSet; + +import static org.mockito.Mockito.withSettings; public abstract class MockJdbcFactory { - - public static DataSource createDataSource(final Object model) { + + /** + * Creates a DataSource that fetches its data by invoking methods on the given object + * Searches for @Query on the object + */ + public static DataSource createDataSource(final Object database) { return (DataSource) Proxy.newProxyInstance(MockJdbcFactory.class.getClassLoader(), new Class[]{DataSource.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("getConnection")) { - return ObjectBackedConnection.createInstance(model); + return ObjectBackedConnection.createInstance(database); } return Defaults.defaultValue(method.getReturnType()); } }); } + /** + * Creates a DataSource that fetches its data by invoking methods on the given object + * Searches for @Query on the object + */ + + + /** + * Gives you the sql methods... and it is also a DataSource so you can inject + */ +/* + public static Z mockDataSource(Class interfaceClass) { + T mock = Mockito.mock(interfaceClass, withSettings().extraInterfaces(javax.sql.DataSource.class)); + return (Z) mock; + } + + public static Z mockResultSet(Class interfaceClass) { + T mock = Mockito.mock(interfaceClass, withSettings().extraInterfaces(javax.sql.DataSource.class)); + return (Z) mock; + } +*/ + + } diff --git a/resultsetmock/src/test/java/play/resultsetmock/IModel.java b/resultsetmock/src/test/java/play/resultsetmock/IModel.java deleted file mode 100644 index 999ca06..0000000 --- a/resultsetmock/src/test/java/play/resultsetmock/IModel.java +++ /dev/null @@ -1,10 +0,0 @@ -package play.resultsetmock; - -import play.baseline.model.Pet; - -import java.util.List; - -public interface IModel { - - List loadPets(String name, int age); -} diff --git a/resultsetmock/src/test/java/play/resultsetmock/Model.java b/resultsetmock/src/test/java/play/resultsetmock/Model.java deleted file mode 100644 index 1312f61..0000000 --- a/resultsetmock/src/test/java/play/resultsetmock/Model.java +++ /dev/null @@ -1,26 +0,0 @@ -package play.resultsetmock; - -import play.baseline.model.Pet; -import play.resultsetmock.annotations.Param; -import play.resultsetmock.annotations.Query; - -import java.util.List; - -public class Model implements IModel { - - IModel model; // so we can verify call - - public Model(IModel model) { - this.model = model; - } - - @Override - @Query("select * from pets") - public List loadPets( - @Param("name") String name, - @Param("age") int age) { - - return model.loadPets(name, age); - } - -} diff --git a/resultsetmock/src/test/java/play/resultsetmock/jdbc/ComponentTest.java b/resultsetmock/src/test/java/play/resultsetmock/jdbc/ComponentTest.java deleted file mode 100644 index 89d32cb..0000000 --- a/resultsetmock/src/test/java/play/resultsetmock/jdbc/ComponentTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package play.resultsetmock.jdbc; - -import org.junit.*; -import play.baseline.Main; - -import java.io.IOException; - -/** - * The system is running in a different VM. - * we mock out db using a mock datasource. - * - */ -public class ComponentTest { - - private static Process server; - - @BeforeClass - public static void startServer() throws IOException, InterruptedException { - String classpath = System.getProperty("java.class.path"); - String className = Main.class.getCanonicalName(); - ProcessBuilder pb = new ProcessBuilder("java", "-cp", classpath, className); - pb.inheritIO(); - server = pb.start(); - Thread.sleep(5000); - } - - @org.junit.Test - public void dummy() throws InterruptedException { - } - - @AfterClass - public static void stopServer() throws IOException { - server.destroy(); - } -} diff --git a/resultsetmock/src/test/java/play/resultsetmock/jdbc/Test.java b/resultsetmock/src/test/java/play/resultsetmock/jdbc/Test.java deleted file mode 100644 index 62a4fd9..0000000 --- a/resultsetmock/src/test/java/play/resultsetmock/jdbc/Test.java +++ /dev/null @@ -1,97 +0,0 @@ -package play.resultsetmock.jdbc; - -import com.google.common.collect.Lists; -import org.junit.Before; -import org.mockito.Mockito; -import play.baseline.model.Pet; -import play.resultsetmock.IModel; -import play.resultsetmock.Model; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.*; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class Test { - - Model proxy; - IModel inner; - - - @Before - public void setup() { - inner = Mockito.mock(IModel.class); - proxy = new Model(inner); - when(inner.loadPets(anyString(), anyInt())).thenReturn( - Lists.newArrayList( -/* - new Pet("pet", 1, "Caner"), - new Pet("pet2", 2, "Caner2") -*/ - new Pet(), - new Pet() - )); - } - - @org.junit.Test - public void testRsOnly() throws SQLException { - - ResultSet rs = null; -// ResultSet rs = MockJdbcFactory.createResultSet(proxy.loadPets(null, 0)); - - assertResultSet(rs); - } - - @org.junit.Test - public void testFromDs() throws SQLException { - DataSource ds = MockJdbcFactory.createDataSource(proxy); - - Connection conn = ds.getConnection(); - PreparedStatement ps = null; - ResultSet rs = null; - try { - String sql = "select * from pets"; - ps = conn.prepareStatement(sql); - ps.setString(1, "argName"); - ps.setInt(2, 44); - rs = ps.executeQuery(); - - assertResultSet(rs); - } finally { - try { - rs.close(); - ps.close(); - conn.close(); - } catch (Exception e) { - } - } - - verify(inner).loadPets(eq("argName"), eq(44)); - } - - private void assertResultSet(ResultSet rs) throws SQLException { - int i = 0; - while(rs.next()) { - if (i == 0) { - assertEquals("pet", rs.getString("name")); - assertEquals(1, rs.getInt("age")); - assertEquals("Caner", rs.getString("owner_name")); - } else if (i == 1) { - assertEquals("pet2", rs.getString("name")); - assertEquals(2, rs.getInt("age")); - assertEquals("Caner2", rs.getString("owner_name")); - } else { - fail("Only 2 rows are expected"); - } - i++; - } - } - -}