diff --git a/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java b/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java
new file mode 100644
index 0000000..026a9bc
--- /dev/null
+++ b/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java
@@ -0,0 +1,525 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.ofagent.rest;
+
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.Sets;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onlab.rest.BaseResource;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.ofagent.api.OFAgent;
+import org.onosproject.ofagent.api.OFAgentAdminService;
+import org.onosproject.ofagent.api.OFAgentService;
+import org.onosproject.ofagent.api.OFController;
+import org.onosproject.ofagent.impl.DefaultOFAgent;
+import org.onosproject.ofagent.impl.DefaultOFController;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.Set;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.onosproject.ofagent.api.OFAgent.State.STOPPED;
+
+
+/**
+ * Test class for OFAgent application REST resource.
+ */
+public class OFAgentWebResourceTest extends JerseyTest {
+
+
+    private static final Set<OFController> CONTROLLER_SET_1 = Sets.newHashSet(
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.1.4"),
+                    TpPort.tpPort(6633)));
+
+    private static final Set<OFController> CONTROLLER_SET_2 = Sets.newHashSet(
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.4.25"),
+                    TpPort.tpPort(6633)),
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.4.27"),
+                    TpPort.tpPort(6653)));
+
+    private static final Set<OFController> CONTROLLER_SET = Sets.newHashSet(
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.2.11"),
+                    TpPort.tpPort(6633)),
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.2.9"),
+                    TpPort.tpPort(6633)),
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.2.17"),
+                    TpPort.tpPort(6653)));
+
+    private static final NetworkId NETWORK_1 = NetworkId.networkId(1);
+    private static final NetworkId NETWORK_2 = NetworkId.networkId(2);
+    private static final NetworkId NETWORK = NetworkId.networkId(3);
+
+    private static final OFAgent OF_AGENT = DefaultOFAgent.builder()
+            .networkId(NETWORK)
+            .controllers(CONTROLLER_SET)
+            .state(STOPPED)
+            .build();
+
+    private Set<OFAgent> agents = Sets.newHashSet(DefaultOFAgent.builder()
+                                                  .networkId(NETWORK_1)
+                                                  .controllers(CONTROLLER_SET_1)
+                                                  .state(STOPPED)
+                                                  .build(),
+                                          DefaultOFAgent.builder()
+                                                  .networkId(NETWORK_2)
+                                                  .controllers(CONTROLLER_SET_2)
+                                                  .state(STOPPED)
+                                                  .build(),
+                                          OF_AGENT);
+
+    private Set<OFAgent> empty = Sets.newHashSet();
+
+    private final OFAgentAdminService mockOFAgentAdminService = createMock(OFAgentAdminService.class);
+    private final OFAgentService mockOFAgentService = createMock(OFAgentService.class);
+
+    /**
+     * Constructs OFAgent Web application test instance.
+     */
+    public OFAgentWebResourceTest() {
+        super(ResourceConfig.forApplicationClass(OFAgentWebApplication.class));
+    }
+
+    /**
+     * Sets up the global values for all the tests.
+     */
+    @Before
+    public void setUpMocks() {
+        ServiceDirectory testDirectory = new TestServiceDirectory()
+                .add(OFAgentAdminService.class, mockOFAgentAdminService)
+                .add(OFAgentService.class, mockOFAgentService);
+        BaseResource.setServiceDirectory(testDirectory);
+    }
+
+    /**
+     * Cleans up.
+     */
+    @After
+    public void tearDownMocks() {
+    }
+
+    /**
+     * Tests the result of the rest api GET when there are OFAgents.
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNonEmptyOFAgentSet() throws IOException {
+        expect(mockOFAgentService.agents()).andReturn(agents).anyTimes();
+        replay(mockOFAgentService);
+
+        final WebTarget wt = target();
+        assertNotNull("WebTarget is null", wt);
+        assertNotNull("WebTarget request is null", wt.request());
+        final String response = wt.path("service/ofagents").request().get(String.class);
+        final JsonObject result = Json.parse(response).asObject();
+        assertThat(result, notNullValue());
+        assertThat(result.names(), hasSize(1));
+        assertThat(result.names().get(0), is("ofAgents"));
+
+        mockOFAgentService.agents().forEach(ofAgent -> {
+
+            String expectedJsonStringNetworkId = "\"networkId\":\"" + ofAgent.networkId().id() + "\"";
+            assertThat(response, containsString(expectedJsonStringNetworkId));
+
+            String expectedJsonStringState = "\"state\":\"" + ofAgent.state() + "\"";
+            assertThat(response, containsString(expectedJsonStringState));
+
+            ofAgent.controllers().forEach(ofController -> {
+                String expectedJsonStringIP = "\"ip\":\"" + ofController.ip() + "\"";
+                assertThat(response, containsString(expectedJsonStringIP));
+
+                String expectedJsonStringPort = "\"port\":\"" + ofController.port() + "\"";
+                assertThat(response, containsString(expectedJsonStringPort));
+            });
+        });
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests the result of the rest api GET when there are no OFAgents.
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testEmptyOFAgentSet() throws IOException {
+        expect(mockOFAgentService.agents()).andReturn(empty).anyTimes();
+        replay(mockOFAgentService);
+
+        final WebTarget wt = target();
+        assertNotNull("WebTarget is null", wt);
+        assertNotNull("WebTarget request is null", wt.request());
+        final String response = wt.path("service/ofagents").request().get(String.class);
+        final JsonObject result = Json.parse(response).asObject();
+        assertThat(result, notNullValue());
+        assertThat(result.names(), hasSize(1));
+        assertThat(response, is("{\"ofAgents\":[]}"));
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests the result of the rest api GET for OFAgent.
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testOFAgent() throws IOException {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        final WebTarget wt = target();
+        assertNotNull("WebTarget is null", wt);
+        assertNotNull("WebTarget request is null", wt.request());
+        final Response response = wt.path("service/ofagent/" + NETWORK).request().get();
+        final JsonObject result = Json.parse(response.readEntity(String.class)).asObject();
+        assertThat(result, notNullValue());
+        assertThat(result.names(), hasSize(3));
+        assertThat(result.get("networkId").asString(), is(NETWORK.id().toString()));
+        assertThat(result.get("state").asString(), is(STOPPED.toString()));
+
+        verify(mockOFAgentService);
+    }
+
+
+    /**
+     * Tests the result of the rest api GET for non-existent OFAgent.
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNonExistentOFAgent() throws IOException {
+        expect(mockOFAgentService.agent(anyObject())).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        final WebTarget wt = target();
+        assertNotNull("WebTarget is null", wt);
+        assertNotNull("WebTarget request is null", wt.request());
+        final Response response = wt.path("service/ofagent/" + NETWORK_1).request().get();
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
+
+        verify(mockOFAgentService);
+    }
+
+
+    /**
+     * Tests creating an OFAgent with POST.
+     */
+    @Test
+    public void testOFAgentCreate() {
+        mockOFAgentAdminService.createAgent(anyObject());
+        expectLastCall().anyTimes();
+        replay(mockOFAgentAdminService);
+
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-ofagent-create.json");
+        assertNotNull("post-ofagent-create.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-create")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
+
+        verify(mockOFAgentAdminService);
+    }
+
+    /**
+     * Tests creating an OFAgent with bad POST request.
+     */
+    @Test
+    public void testOFAgentCreateBadRequest() {
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-bad-request.json");
+        assertNotNull("post-bad-request.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-create")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_INTERNAL_ERROR));
+    }
+
+    /**
+     * Tests updating an OFAgent with PUT.
+     */
+    @Test
+    public void testOFAgentUpdate() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        mockOFAgentAdminService.updateAgent(anyObject());
+        expectLastCall().anyTimes();
+        replay(mockOFAgentAdminService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("put-ofagent-update.json");
+        assertNotNull("put-ofagent-update.json is null", jsonStream);
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-update")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+        assertThat(response.readEntity(String.class), containsString("OFAgent updated"));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+
+    }
+
+    /**
+     * Tests non-existent OFAgent updating with PUT.
+     */
+    @Test
+    public void testNonExistentOFAgentUpdate() {
+        expect(mockOFAgentService.agent(anyObject())).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("put-non-existent-ofagent-update.json");
+        assertNotNull("put-non-existent-ofagent-update.json is null", jsonStream);
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-update")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
+
+        verify(mockOFAgentService);
+
+    }
+
+    /**
+     * Tests OFAgent updating with bad PUT request.
+     */
+    @Test
+    public void testOFAgentUpdateBadRequest() {
+        expect(mockOFAgentService.agent(anyObject())).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("put-bad-request.json");
+        assertNotNull("put-bad-request.json is null", jsonStream);
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-update")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_INTERNAL_ERROR));
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests starting an OFAgent with POST.
+     */
+    @Test
+    public void testOFAgentStart() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        mockOFAgentAdminService.startAgent(anyObject());
+        expectLastCall().anyTimes();
+        replay(mockOFAgentAdminService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-ofagent-start.json");
+        assertNotNull("post-ofagent-create.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-start")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+//        assertThat(response.readEntity(String.class), containsString("OFAgent started"));
+        assertThat(response.readEntity(String.class), is("OFAgent started"));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+    }
+
+    /**
+     * Tests non-existent OFAgent starting with POST.
+     */
+    @Test
+    public void testNonExistentOFAgentStart() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-non-existent-ofagent-start.json");
+        assertNotNull("post-non-existent-ofagent-start.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-start")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests OFAgent starting with bad POST request.
+     */
+    @Test
+    public void testOFAgentStartBadRequest() {
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-bad-request.json");
+        assertNotNull("post-bad-request.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-start")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
+
+    }
+
+    /**
+     * Tests stopping an OFAgent with POST.
+     */
+    @Test
+    public void testOFAgentStop() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        mockOFAgentAdminService.stopAgent(anyObject());
+        expectLastCall().anyTimes();
+        replay(mockOFAgentAdminService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-ofagent-stop.json");
+        assertNotNull("post-ofagent-stop.json is null", jsonStream);
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-stop")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+    }
+
+    /**
+     * Tests stopping non-existent OFAgent with POST.
+     */
+    @Test
+    public void testNonExistentOFAgentStop() {
+        expect(mockOFAgentService.agent(NETWORK)).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-non-existent-ofagent-stop.json");
+        assertNotNull("post-non-existent-ofagent-stop.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-stop")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests stopping FAgent with bad POST request.
+     */
+    @Test
+    public void testOFAgentStopBadRequest() {
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-bad-request.json");
+        assertNotNull("post-bad-request.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-stop")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_INTERNAL_ERROR));
+    }
+
+
+    /**
+     * Tests deleting an OFAgent with DELETE.
+     */
+    @Test
+    public void testOFAgentRemove() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        expect(mockOFAgentAdminService.removeAgent(NETWORK)).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentAdminService);
+
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-remove/" + NETWORK.toString())
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .delete();
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+        final JsonObject result = Json.parse(response.readEntity(String.class)).asObject();
+        assertThat(result.get("networkId").asString(), is(NETWORK.id().toString()));
+        assertThat(result.get("state").asString(), is(STOPPED.toString()));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+    }
+
+    /**
+     * Tests deleting a non-existent OFAgent with DELETE.
+     */
+    @Test
+    public void testNonExistentOFAgentRemove() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        expect(mockOFAgentAdminService.removeAgent(NETWORK)).andReturn(null).anyTimes();
+        replay(mockOFAgentAdminService);
+
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-remove/" + NETWORK.toString())
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .delete();
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
+        assertThat(response.readEntity(String.class), containsString("OFAgent not found"));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+    }
+}
