package com.ligati.apipixie;
import com.ligati.apipixie.exception.APIUsageException;
import com.ligati.apipixie.http.APIHttpManager;
import com.ligati.apipixie.model.*;
import com.ligati.apipixie.tools.AnnotationUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
@RunWith(JUnit4.class)
public class APIServiceTest {
private APIPixie pixie;
private APIHttpManager http;
private static Long IDS = 1L;
@Rule
public ExpectedException expectedEx = ExpectedException.none();
@Before
public void setUp() {
this.pixie = mock(APIPixie.class);
this.http = mock(APIHttpManager.class);
}
@Test
public void getAll_returns_a_list() throws JSONException {
// GIVEN
String text1 = "my text 1";
String text2 = "my text 2";
JSONArray array = new JSONArray();
JSONObject entity1 = generateEntityJSON(text1);
JSONObject entity2 = generateEntityJSON(text2);
array.put(entity1);
array.put(entity2);
when(this.http.getArray(anyString())).thenReturn(array);
APIService<Entity, Long> service = new APIService<>(pixie, Entity.class, http);
// WHEN
List<Entity> entities = service.getAll();
// THEN
assertEquals(2, entities.size());
assertEquals(text1, entities.get(0).getText());
assertEquals(text2, entities.get(1).getText());
}
@Test
public void if_no_specific_config_the_url_is_the_apiURL_plus_the_name_of_the_entity_in_plural_form() {
// GIVEN
String apiUrl = "http://myapi.com";
when(pixie.getAPIUrl()).thenReturn(apiUrl);
when(this.http.getArray(anyString())).thenReturn(new JSONArray());
APIService<Entity, Long> service = new APIService<>(pixie, Entity.class, http);
// WHEN
service.getAll();
// THEN
String url = apiUrl + "/entities";
verify(this.http).getArray(url);
}
@Test
public void if_the_annotation_specifies_an_url_the_requestUrl_should_be_the_apiURL_plus_the_custom_url() {
// GIVEN
String apiUrl = "http://myapi.com";
when(pixie.getAPIUrl()).thenReturn(apiUrl);
when(this.http.getArray(anyString())).thenReturn(new JSONArray());
APIService<EntityWithUrl, Long> service = new APIService<>(pixie, EntityWithUrl.class, http);
// WHEN
service.getAll();
// THEN
String url = apiUrl + "/" + AnnotationUtil.getEntityUrl(EntityWithUrl.class);
verify(this.http).getArray(url);
}
@Test
public void get_returns_the_entity() throws JSONException {
// GIVEN
String text = "my text";
JSONObject json = generateEntityJSON(text);
Long id = json.getLong("id");
when(this.http.getObject(anyString())).thenReturn(json);
APIService<Entity, Long> service = new APIService<>(pixie, Entity.class, http);
// WHEN
Entity entity = service.get(id);
// THEN
assertEquals(id, entity.getId());
assertEquals(text, entity.getText());
}
@Test
public void put_updates_and_returns_the_entity() throws JSONException {
// GIVEN
String text = "my text";
JSONObject json = generateEntityJSON(text);
Long id = json.getLong("id");
when(this.http.putObject(anyString(), any(JSONObject.class))).thenReturn(json);
APIService<Entity, Long> service = new APIService<>(pixie, Entity.class, http);
Entity modified = new Entity();
modified.setId(id);
modified.setText(text);
// WHEN
Entity entity = service.put(modified);
// THEN
assertEquals(id, entity.getId());
assertEquals(text, entity.getText());
verify(this.http).putObject(anyString(), any(JSONObject.class));
}
@Test
public void post_creates_and_returns_the_entity_with_its_id() throws JSONException {
// GIVEN
String text = "my text";
Entity entity = new Entity();
entity.setText(text);
APIService<Entity, Long> service = new APIService<>(pixie, Entity.class, http);
Long id = 42L;
JSONObject json = generateEntityJSON(text);
json.put("id", id);
when(this.http.postObject(anyString(), any(JSONObject.class))).thenReturn(json);
// WHEN
Entity created = service.post(entity);
// THEN
assertEquals(id, created.getId());
assertEquals(text, created.getText());
verify(this.http).postObject(anyString(), any(JSONObject.class));
}
@Test
public void delete_deletes_the_entity() throws JSONException {
// GIVEN
Long id = 42L;
String text = "my text";
Entity entity = new Entity();
entity.setId(id);
entity.setText(text);
APIService<Entity, Long> service = new APIService<>(pixie, Entity.class, http);
// WHEN
service.delete(entity);
// THEN
verify(this.http).deleteObject(anyString());
}
@Test
public void delete_if_null_entity_fails() throws JSONException {
// GIVEN
APIService<Entity, Long> service = new APIService<>(pixie, Entity.class, http);
// THEN
verifyZeroInteractions(this.http);
this.expectedEx.expect(APIUsageException.class);
// WHEN
service.delete(null);
}
@Test
public void delete_if_no_id_fails() throws JSONException {
// GIVEN
Entity entity = new Entity();
APIService<Entity, Long> service = new APIService<>(pixie, Entity.class, http);
// THEN
verifyZeroInteractions(this.http);
this.expectedEx.expect(APIUsageException.class);
// WHEN
service.delete(entity);
}
@Test
public void delete_with_id_deletes_the_entity() throws JSONException {
// GIVEN
Long id = 42L;
APIService<Entity, Long> service = new APIService<>(pixie, Entity.class, http);
// WHEN
service.deleteById(id);
// THEN
verify(this.http).deleteObject(anyString());
}
private static JSONObject generateEntityJSON(String text) throws JSONException {
JSONObject entity = new JSONObject();
entity.put("id", IDS++);
entity.put("text", text);
return entity;
}
@Test
public void jsonObjectToEntity_with_an_array_and_a_basic_collection_maps_the_array() throws JSONException {
// GIVEN
APIService<EntityWithBasicCollectionAPICollection, Long> service = new APIService<>(pixie, EntityWithBasicCollectionAPICollection.class, http);
JSONObject json = new JSONObject();
JSONArray array = new JSONArray();
array.put("first");
array.put("second");
json.put("strings", array);
// WHEN
EntityWithBasicCollectionAPICollection entity = service.jsonObjectToEntity(json);
// THEN
assertEquals(2, entity.getStrings().size());
assertEquals("first", entity.getStrings().get(0));
assertEquals("second", entity.getStrings().get(1));
}
@Test
public void jsonObjectToEntity_with_an_array_and_an_APIEntity_collection_maps_the_array() throws JSONException {
// GIVEN
APIService<EntityWithEntityCollectionAPICollection, Long> service = new APIService<>(pixie, EntityWithEntityCollectionAPICollection.class, http);
JSONObject json = new JSONObject();
JSONArray array = new JSONArray();
JSONObject entity1 = new JSONObject();
entity1.put("id", 42);
array.put(entity1);
JSONObject entity2 = new JSONObject();
entity2.put("id", 43);
array.put(entity2);
json.put("entities", array);
// WHEN
EntityWithEntityCollectionAPICollection entity = service.jsonObjectToEntity(json);
// THEN
assertEquals(2, entity.getEntities().size());
assertEquals(new Long(42), entity.getEntities().get(0).getId());
assertEquals(new Long(43), entity.getEntities().get(1).getId());
}
@Test
public void jsonObjectToEntity_with_a_nested_APIEntity_maps_the_entity() throws JSONException {
// GIVEN
APIService<EntityWithNestedEntity, Long> service = new APIService<>(pixie, EntityWithNestedEntity.class, http);
JSONObject json = new JSONObject();
json.put("id", 42);
JSONObject nested = new JSONObject();
nested.put("id", 43);
json.put("entity", nested);
// WHEN
EntityWithNestedEntity entity = service.jsonObjectToEntity(json);
// THEN
assertEquals(new Long(42), entity.getId());
assertEquals(new Long(43), entity.getEntity().getId());
}
@Test
public void entityToJsonObject_with_an_array_and_a_basic_collection_maps_the_array() throws JSONException {
// GIVEN
APIService<EntityWithBasicCollectionAPICollection, Long> service = new APIService<>(pixie, EntityWithBasicCollectionAPICollection.class, http);
EntityWithBasicCollectionAPICollection entity = new EntityWithBasicCollectionAPICollection();
entity.setId(42L);
ArrayList<String> strings = new ArrayList<>();
strings.add("first");
strings.add("second");
entity.setStrings(strings);
// WHEN
JSONObject json = service.entityToJsonObject(entity);
// THEN
assertEquals(42L, json.getLong("id"));
assertEquals(2, json.getJSONArray("strings").length());
assertEquals("first", json.getJSONArray("strings").getString(0));
assertEquals("second", json.getJSONArray("strings").getString(1));
}
@Test
public void entityToJsonObject_with_a_nested_APIEntity_maps_the_entity() throws JSONException {
// GIVEN
APIService<EntityWithNestedEntity, Long> service = new APIService<>(pixie, EntityWithNestedEntity.class, http);
Entity nested = new Entity();
nested.setId(31L);
nested.setText("my custom text");
EntityWithNestedEntity entity = new EntityWithNestedEntity();
entity.setId(42L);
entity.setEntity(nested);
// WHEN
JSONObject json = service.entityToJsonObject(entity);
// THEN
assertEquals(42L, json.getLong("id"));
assertEquals(31L, json.getJSONObject("entity").getLong("id"));
assertEquals("my custom text", json.getJSONObject("entity").getString("text"));
}
@Test
public void entityToJsonObject_with_an_array_and_an_APIEntity_collection_maps_the_array() throws JSONException {
// GIVEN
APIService<EntityWithEntityCollectionAPICollection, Long> service = new APIService<>(pixie, EntityWithEntityCollectionAPICollection.class, http);
List<Entity> nested = new LinkedList<>();
Entity nested1 = new Entity();
nested1.setId(11L);
nested1.setText("first nested entity");
nested.add(nested1);
Entity nested2 = new Entity();
nested2.setId(22L);
nested2.setText("second nested entity");
nested.add(nested2);
EntityWithEntityCollectionAPICollection entity = new EntityWithEntityCollectionAPICollection();
entity.setId(33L);
entity.setEntities(nested);
// WHEN
JSONObject json = service.entityToJsonObject(entity);
// THEN
assertEquals(33L, json.getLong("id"));
assertEquals(2, json.getJSONArray("entities").length());
JSONObject obj1 = json.getJSONArray("entities").getJSONObject(0);
assertEquals(11L, obj1.getLong("id"));
assertEquals("first nested entity", obj1.getString("text"));
JSONObject obj2 = json.getJSONArray("entities").getJSONObject(1);
assertEquals(22L, obj2.getLong("id"));
assertEquals("second nested entity", obj2.getString("text"));
}
}