Skip to content

Commit f051dce

Browse files
author
Takashi Matsuo
committed
Extracted code snippets from the unittest docs and added travis config.
1 parent 20e5204 commit f051dce

16 files changed

+647
-0
lines changed

.travis.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
language: java
2+
3+
env:
4+
- TEST_DIR=unittests
5+
6+
script: cd $TEST_DIR && mvn test

unittests/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# appengine-ndb-snippets
2+
3+
## unittests
4+
5+
This subdirectory contains code snippets for [Local Unit Testing for Java](https://cloud.google.com/appengine/docs/java/tools/localunittesting).

unittests/pom.xml

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
4+
<modelVersion>4.0.0</modelVersion>
5+
<packaging>war</packaging>
6+
<version>1.0-SNAPSHOT</version>
7+
8+
<groupId>com.google.appengine.samples.unittest</groupId>
9+
<artifactId>unittests</artifactId>
10+
11+
<properties>
12+
<appengine.app.version>1</appengine.app.version>
13+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
14+
</properties>
15+
16+
<prerequisites>
17+
<maven>3.1.0</maven>
18+
</prerequisites>
19+
20+
<dependencies>
21+
<!-- Compile/runtime dependencies -->
22+
<dependency>
23+
<groupId>com.google.appengine</groupId>
24+
<artifactId>appengine-api-1.0-sdk</artifactId>
25+
<version>1.9.18</version>
26+
</dependency>
27+
<dependency>
28+
<groupId>javax.servlet</groupId>
29+
<artifactId>servlet-api</artifactId>
30+
<version>2.5</version>
31+
<scope>provided</scope>
32+
</dependency>
33+
<dependency>
34+
<groupId>jstl</groupId>
35+
<artifactId>jstl</artifactId>
36+
<version>1.2</version>
37+
</dependency>
38+
39+
<!-- Test Dependencies -->
40+
<dependency>
41+
<groupId>junit</groupId>
42+
<artifactId>junit</artifactId>
43+
<version>4.12</version>
44+
<scope>test</scope>
45+
</dependency>
46+
<dependency>
47+
<groupId>com.google.appengine</groupId>
48+
<artifactId>appengine-testing</artifactId>
49+
<version>1.9.18</version>
50+
<scope>test</scope>
51+
</dependency>
52+
<dependency>
53+
<groupId>com.google.appengine</groupId>
54+
<artifactId>appengine-api-stubs</artifactId>
55+
<version>1.9.18</version>
56+
<scope>test</scope>
57+
</dependency>
58+
</dependencies>
59+
60+
<build>
61+
<!-- for hot reload of the web application-->
62+
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
63+
<plugins>
64+
<plugin>
65+
<groupId>org.codehaus.mojo</groupId>
66+
<artifactId>versions-maven-plugin</artifactId>
67+
<version>2.1</version>
68+
<executions>
69+
<execution>
70+
<phase>compile</phase>
71+
<goals>
72+
<goal>display-dependency-updates</goal>
73+
<goal>display-plugin-updates</goal>
74+
</goals>
75+
</execution>
76+
</executions>
77+
</plugin>
78+
<plugin>
79+
<groupId>org.apache.maven.plugins</groupId>
80+
<version>3.1</version>
81+
<artifactId>maven-compiler-plugin</artifactId>
82+
<configuration>
83+
<source>1.7</source>
84+
<target>1.7</target>
85+
</configuration>
86+
</plugin>
87+
<plugin>
88+
<groupId>org.apache.maven.plugins</groupId>
89+
<artifactId>maven-war-plugin</artifactId>
90+
<version>2.4</version>
91+
<configuration>
92+
<archiveClasses>true</archiveClasses>
93+
<webResources>
94+
<!-- in order to interpolate version from pom into appengine-web.xml -->
95+
<resource>
96+
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
97+
<filtering>true</filtering>
98+
<targetPath>WEB-INF</targetPath>
99+
</resource>
100+
</webResources>
101+
</configuration>
102+
</plugin>
103+
104+
<plugin>
105+
<groupId>com.google.appengine</groupId>
106+
<artifactId>appengine-maven-plugin</artifactId>
107+
<version>1.9.18</version>
108+
<configuration>
109+
<enableJarClasses>false</enableJarClasses>
110+
<!-- Comment in the below snippet to bind to all IPs instead of just localhost -->
111+
<!-- address>0.0.0.0</address>
112+
<port>8080</port -->
113+
<!-- Comment in the below snippet to enable local debugging with a remove debugger
114+
like those included with Eclipse or IntelliJ -->
115+
<!-- jvmFlags>
116+
<jvmFlag>-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n</jvmFlag>
117+
</jvmFlags -->
118+
</configuration>
119+
</plugin>
120+
<plugin>
121+
<groupId>org.apache.maven.plugins</groupId>
122+
<artifactId>maven-checkstyle-plugin</artifactId>
123+
<version>2.15</version>
124+
<executions>
125+
<execution>
126+
<id>checkstyle</id>
127+
<phase>validate</phase>
128+
<goals>
129+
<goal>check</goal>
130+
</goals>
131+
<configuration>
132+
<failOnViolation>true</failOnViolation>
133+
</configuration>
134+
</execution>
135+
</executions>
136+
</plugin>
137+
</plugins>
138+
</build>
139+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
3+
<application>your-app-id</application>
4+
<version>${appengine.app.version}</version>
5+
<threadsafe>true</threadsafe>
6+
7+
<system-properties>
8+
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
9+
</system-properties>
10+
</appengine-web-app>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# A default java.util.logging configuration.
2+
# (All App Engine logging is through java.util.logging by default).
3+
#
4+
# To use this configuration, copy it into your application's WEB-INF
5+
# folder and add the following to your appengine-web.xml:
6+
#
7+
# <system-properties>
8+
# <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
9+
# </system-properties>
10+
#
11+
12+
# Set the default logging level for all loggers to WARNING
13+
.level = WARNING
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
3+
4+
</web-app>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.google.appengine.samples.unittest;
2+
3+
// [START auth]
4+
import com.google.appengine.api.users.UserService;
5+
import com.google.appengine.api.users.UserServiceFactory;
6+
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
7+
import com.google.appengine.tools.development.testing.LocalUserServiceTestConfig;
8+
import org.junit.After;
9+
import org.junit.Before;
10+
import org.junit.Test;
11+
12+
import static org.junit.Assert.*;
13+
14+
public class AuthenticationTest {
15+
16+
private final LocalServiceTestHelper helper =
17+
new LocalServiceTestHelper(new LocalUserServiceTestConfig())
18+
.setEnvIsAdmin(true).setEnvIsLoggedIn(true);
19+
20+
@Before
21+
public void setUp() {
22+
helper.setUp();
23+
}
24+
25+
@After
26+
public void tearDown() {
27+
helper.tearDown();
28+
}
29+
30+
@Test
31+
public void testIsAdmin() {
32+
UserService userService = UserServiceFactory.getUserService();
33+
assertTrue(userService.isUserAdmin());
34+
}
35+
}
36+
// [END auth]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.google.appengine.samples.unittest;
2+
3+
// [START local_capabilities]
4+
import com.google.appengine.api.capabilities.Capability;
5+
import com.google.appengine.api.capabilities.CapabilityStatus;
6+
import com.google.appengine.api.datastore.DatastoreService;
7+
import com.google.appengine.api.datastore.DatastoreServiceFactory;
8+
import com.google.appengine.api.datastore.FetchOptions;
9+
import com.google.appengine.api.datastore.Query;
10+
import com.google.appengine.tools.development.testing.LocalCapabilitiesServiceTestConfig;
11+
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
12+
import com.google.apphosting.api.ApiProxy;
13+
import org.junit.After;
14+
import org.junit.Test;
15+
16+
import static org.junit.Assert.*;
17+
18+
public class CapabilitiesTest {
19+
20+
private LocalServiceTestHelper helper;
21+
22+
@After
23+
public void tearDown() {
24+
helper.tearDown();
25+
}
26+
27+
@Test(expected = ApiProxy.CapabilityDisabledException.class)
28+
public void testDisabledDatastore() {
29+
Capability testOne = new Capability("datastore_v3");
30+
CapabilityStatus testStatus = CapabilityStatus.DISABLED;
31+
//Initialize
32+
LocalCapabilitiesServiceTestConfig config =
33+
new LocalCapabilitiesServiceTestConfig().setCapabilityStatus(testOne, testStatus);
34+
helper = new LocalServiceTestHelper(config);
35+
helper.setUp();
36+
FetchOptions fo = FetchOptions.Builder.withLimit(10);
37+
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
38+
assertEquals(0, ds.prepare(new Query("yam")).countEntities(fo));
39+
}
40+
}
41+
// [END local_capabilities]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.google.appengine.samples.unittest;
2+
3+
// [START taskqueue_example_2]
4+
import com.google.appengine.api.taskqueue.DeferredTask;
5+
import com.google.appengine.api.taskqueue.QueueFactory;
6+
import com.google.appengine.api.taskqueue.TaskOptions;
7+
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
8+
import com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig;
9+
import org.junit.After;
10+
import org.junit.Before;
11+
import org.junit.Test;
12+
13+
import java.util.concurrent.TimeUnit;
14+
15+
import static org.junit.Assert.*;
16+
17+
public class DeferredTaskTest {
18+
19+
// Unlike CountDownLatch, TaskCountDownlatch lets us reset.
20+
private final LocalTaskQueueTestConfig.TaskCountDownLatch latch =
21+
new LocalTaskQueueTestConfig.TaskCountDownLatch(1);
22+
23+
private final LocalServiceTestHelper helper =
24+
new LocalServiceTestHelper(new LocalTaskQueueTestConfig()
25+
.setDisableAutoTaskExecution(false)
26+
.setCallbackClass(LocalTaskQueueTestConfig.DeferredTaskCallback.class)
27+
.setTaskExecutionLatch(latch));
28+
29+
private static class MyTask implements DeferredTask {
30+
private static boolean taskRan = false;
31+
32+
@Override
33+
public void run() {
34+
taskRan = true;
35+
}
36+
}
37+
38+
@Before
39+
public void setUp() {
40+
helper.setUp();
41+
}
42+
43+
@After
44+
public void tearDown() {
45+
MyTask.taskRan = false;
46+
latch.reset();
47+
helper.tearDown();
48+
}
49+
50+
@Test
51+
public void testTaskGetsRun() throws InterruptedException {
52+
QueueFactory.getDefaultQueue().add(
53+
TaskOptions.Builder.withPayload(new MyTask()));
54+
assertTrue(latch.await(5, TimeUnit.SECONDS));
55+
assertTrue(MyTask.taskRan);
56+
}
57+
}
58+
// [END taskqueue_example_2]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.google.appengine.samples.unittest;
2+
3+
import com.google.appengine.api.datastore.DatastoreService;
4+
import com.google.appengine.api.datastore.DatastoreServiceFactory;
5+
import com.google.appengine.api.datastore.Entity;
6+
import com.google.appengine.api.datastore.Key;
7+
import com.google.appengine.api.datastore.Query;
8+
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
9+
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
10+
import org.junit.After;
11+
import org.junit.Before;
12+
import org.junit.Test;
13+
14+
import static com.google.appengine.api.datastore.FetchOptions.Builder.withLimit;
15+
import static org.junit.Assert.*;
16+
17+
// [START HRD_example_2]
18+
// ...
19+
import com.google.appengine.api.datastore.dev.HighRepJobPolicy;
20+
21+
public class LocalCustomPolicyHighRepDatastoreTest {
22+
private static final class CustomHighRepJobPolicy implements HighRepJobPolicy {
23+
static int count = 0;
24+
@Override
25+
public boolean shouldApplyNewJob(Key entityGroup) {
26+
// every other new job fails to apply
27+
return count++ % 2 == 0;
28+
}
29+
30+
@Override
31+
public boolean shouldRollForwardExistingJob(Key entityGroup) {
32+
// every other existing job fails to apply
33+
return count++ % 2 == 0;
34+
}
35+
}
36+
37+
private final LocalServiceTestHelper helper =
38+
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
39+
.setAlternateHighRepJobPolicyClass(CustomHighRepJobPolicy.class));
40+
41+
@Before
42+
public void setUp() {
43+
helper.setUp();
44+
}
45+
46+
@After
47+
public void tearDown() {
48+
helper.tearDown();
49+
}
50+
51+
@Test
52+
public void testEventuallyConsistentGlobalQueryResult() {
53+
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
54+
ds.put(new Entity("yam")); // applies
55+
ds.put(new Entity("yam")); // does not apply
56+
// first global query only sees the first Entity
57+
assertEquals(1, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
58+
// second global query sees both Entities because we "groom" (attempt to
59+
// apply unapplied jobs) after every query
60+
assertEquals(2, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
61+
}
62+
}
63+
// [END HRD_example_2]

0 commit comments

Comments
 (0)