package com.getbase.android.db.fluentsqlite;
import static com.getbase.android.db.fluentsqlite.Insert.insert;
import static com.getbase.android.db.fluentsqlite.Query.select;
import static com.google.common.truth.Truth.assertThat;
import static org.fest.assertions.api.ANDROID.assertThat;
import static org.fest.assertions.api.android.content.ContentValuesEntry.entry;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import com.getbase.android.db.fluentsqlite.Insert.DefaultValuesInsert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class InsertTest {
@Mock
private SQLiteDatabase mDb;
@Mock
private SQLiteStatement mStatement;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mDb.compileStatement(anyString())).thenReturn(mStatement);
}
@Test
public void shouldUseTableSpecifiedInIntoStepInInsertForDefaultValues() throws Exception {
DefaultValuesInsert insert = insert().into("A").defaultValues("nullable_col");
assertThat(insert.mTable).isEqualTo("A");
}
@Test
public void shouldUseTableSpecifiedInIntoStepInInsertWithValues() throws Exception {
Insert insert = insert().into("A").value("nullable_col", null);
assertThat(insert.mTable).isEqualTo("A");
}
@Test
public void shouldBuildTheInsertForDefaultValues() throws Exception {
DefaultValuesInsert insert = insert().into("A").defaultValues("nullable_col");
assertThat(insert.mNullColumnHack).isEqualTo("nullable_col");
}
@Test
public void shouldBuildTheInsertInSelectFormWithoutSpecifiedColumns() throws Exception {
Query query = select().allColumns().from("B").build();
insert().into("A").resultOf(query).perform(mDb);
verify(mDb).compileStatement(eq("INSERT INTO A " + query.toRawQuery().mRawQuery));
verify(mStatement).executeInsert();
}
@Test
public void shouldAllowUsingQueryWithBoundArgsForInsertInSelectForm() throws Exception {
insert()
.into("A")
.resultOf(select()
.allColumns()
.from("B")
.where("col=?", 0)
.build()
)
.perform(mDb);
verify(mDb).compileStatement(eq("INSERT INTO A SELECT * FROM B WHERE (col=?)"));
verify(mStatement).bindString(eq(1), eq("0"));
verify(mStatement).executeInsert();
}
@Test
public void shouldBuildTheInsertInSelectFormWithSpecifiedColumns() throws Exception {
Query query = select().allColumns().from("B").build();
insert().into("A").columns("a", "b", "c").resultOf(query).perform(mDb);
verify(mDb).compileStatement(eq("INSERT INTO A (a, b, c) " + query.toRawQuery().mRawQuery));
verify(mStatement).executeInsert();
}
@Test
public void shouldConcatenateSpecifiedColumnsForInsertInSelectForm() throws Exception {
Query query = select().allColumns().from("B").build();
insert().into("A").columns("a", "b").columns("c").resultOf(query).perform(mDb);
verify(mDb).compileStatement(eq("INSERT INTO A (a, b, c) " + query.toRawQuery().mRawQuery));
verify(mStatement).executeInsert();
}
@Test(expected = IllegalArgumentException.class)
public void shouldRejectNullColumnsListInInsertInSelectForm() throws Exception {
Query query = select().allColumns().from("B").build();
insert().into("A").columns((String[]) null).resultOf(query).perform(mDb);
}
@Test
public void shouldBuildInsertWithSingleValue() throws Exception {
Insert insert = insert().into("A").value("col1", "val1");
assertThat(insert.mValues).contains(entry("col1", "val1"));
}
@Test
public void shouldNotModifyPassedContentValues() throws Exception {
ContentValues values = new ContentValues();
insert()
.into("A")
.values(values)
.value("key", "value");
assertThat(values.containsKey("key")).isFalse();
ContentValues valuesToConcatenate = new ContentValues();
valuesToConcatenate.put("another_key", "another_value");
insert()
.into("A")
.values(values)
.values(valuesToConcatenate);
assertThat(values.containsKey("another_key")).isFalse();
}
@Test
public void shouldBuildInsertWithConcatenatedContentValues() throws Exception {
ContentValues firstValues = new ContentValues();
firstValues.put("col1", "val1");
ContentValues secondValues = new ContentValues();
secondValues.put("col2", "val2");
Insert insert = insert()
.into("A")
.values(firstValues)
.values(secondValues);
assertThat(insert.mValues).contains(entry("col1", "val1"), entry("col2", "val2"));
}
@Test
public void shouldPerformInsertWithContentValuesOverriddenBySingleValue() throws Exception {
ContentValues values = new ContentValues();
values.put("col1", "val1");
values.put("col2", "val2");
Insert insert = insert()
.into("A")
.values(values)
.value("col2", null);
assertThat(insert.mValues).contains(entry("col1", "val1"), entry("col2", null));
}
@Test
public void shouldPerformInsertWithContentValuesOverriddenByOtherContentValues() throws Exception {
ContentValues firstValues = new ContentValues();
firstValues.put("col1", "val1");
firstValues.put("col2", "val2");
ContentValues secondValues = new ContentValues();
secondValues.putNull("col2");
secondValues.put("col3", "val3");
Insert insert = insert()
.into("A")
.values(firstValues)
.values(secondValues);
assertThat(insert.mValues).contains(entry("col1", "val1"), entry("col3", "val3"), entry("col2", null));
}
@Test
public void shouldPerformInsertWithDefaultValues() throws Exception {
insert()
.into("A")
.defaultValues("nullable_col")
.perform(mDb);
verify(mDb).insert(eq("A"), eq("nullable_col"), isNull(ContentValues.class));
}
@Test
public void shouldPerformInsertWithValues() throws Exception {
insert()
.into("A")
.value("col_a", 42)
.perform(mDb);
ArgumentCaptor<ContentValues> contentValuesArgument = ArgumentCaptor.forClass(ContentValues.class);
verify(mDb).insert(eq("A"), isNull(String.class), contentValuesArgument.capture());
assertThat(contentValuesArgument.getValue()).contains(entry("col_a", 42));
}
@Test(expected = RuntimeException.class)
public void shouldCrashIfPerformOrThrowFailsForInsertWithResultOf() throws Exception {
when(mStatement.executeInsert()).thenReturn(-1L);
Query query = select()
.allColumns().from("B")
.build();
insert()
.into("A")
.columns("c")
.resultOf(query)
.performOrThrow(mDb);
}
@Test
public void shouldReturnInsertedIdIfEverythingGoesFine() throws Exception {
when(mStatement.executeInsert()).thenReturn(5L);
Query query = select().allColumns().from("B").build();
long result = insert()
.into("A")
.columns("c")
.resultOf(query)
.performOrThrow(mDb);
assertThat(result).isEqualTo(5L);
}
@Test
public void shouldUseInsertOrThrowWithinPerformOfThrowOfCommonInsert() throws Exception {
ContentValues contentValues = new ContentValues();
contentValues.put("col_a", 42);
insert()
.into("A")
.values(contentValues)
.performOrThrow(mDb);
verify(mDb).insertOrThrow(eq("A"), isNull(String.class), eq(contentValues));
}
@Test
public void shouldReturnSameResultAsInsertOrThrowForCommonInsert() throws Exception {
when(mDb.insertOrThrow(anyString(), anyString(), any(ContentValues.class))).thenReturn(10L);
long res = insert()
.into("A")
.value("col_a", 42)
.performOrThrow(mDb);
assertThat(res).isEqualTo(10L);
}
@Test
public void shouldUseInsertOrThrowWithinPerformOfThrowOfDefaultValuesInsert() throws Exception {
insert()
.into("A")
.defaultValues("nullable_col")
.performOrThrow(mDb);
verify(mDb).insertOrThrow(eq("A"), eq("nullable_col"), isNull(ContentValues.class));
}
}