为什么仪器室测试得到错误 FOREIGN KEY constraint failed

Why instrumented room test get error FOREIGN KEY constraint failed

我不明白这个错误,我有两个实体任务和项目,一个任务分配给一个项目(见下面的代码)。

但是当我想测试添加一个任务时,我有这个错误: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY 约束失败(代码 787 SQLITE_CONSTRAINT_FOREIGNKEY)

我尝试将 onDelete = CASCADE 添加到 FOREIGNKEY 但我的测试不起作用:/

任务Class

@Entity(tableName = "task_table",
        foreignKeys = @ForeignKey(entity = Project.class,
        parentColumns = "id",
        childColumns = "projectId"))

public class Task {
    /**
     * The unique identifier of the task
     */
    @PrimaryKey(autoGenerate = true)
    public long id;

    private long projectId;

    
    @SuppressWarnings("NullableProblems")
    @NonNull
    private String name.

    private long creationTimestamp;

    public Task(long projectId, @NonNull String name, long creationTimestamp) {
        this.setProjectId(projectId);
        this.setName(name);
        this.setCreationTimestamp(creationTimestamp);
    }
...

TaskDao

@Dao
public interface TaskDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insert(Task task);


    @Query("DELETE  FROM task_table WHERE id = :id")
    void delete(long id);

    @Query("SELECT * FROM task_table ORDER BY id ASC")
    LiveData<List<Task>> getAllTasks();

    @Query("SELECT * FROM task_table WHERE id = :id")
    LiveData<Task> getTaskById(long id);
}

项目Class

@Entity(tableName = "project_table")
public class Project {
    /**
     * The unique identifier of the project
     */
    @PrimaryKey(autoGenerate = true)
    public long id;

    @NonNull
    private  String name;

    @ColorInt
    private  int color;

    public Project(@NonNull String name, @ColorInt int color) {
        this.name = name;
        this.color = color;
    }

ProjectDao

@Dao
public interface ProjectDao {


    @Insert(onConflict = OnConflictStrategy.IGNORE)
    void insert(Project project);

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertAll(List<Project> projects);


    @Query("SELECT * FROM project_table")
    LiveData<List<Project>> getAllProjects();


    @Query("SELECT * FROM project_table WHERE id = :id")
    LiveData<Project> getProjectById(long id);

}

测试仪器:

 @Before
    public void createDb() {
        this.database = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(),
                AppDatabase.class)
                .allowMainThreadQueries()
                .build();

        taskDao = database.taskDao();
        projectDao = database.projectDao();
    }

    @After
    public void closeDb() {
        database.close();
    }
@Test
    public void addTask() {

        Project project = new Project("toto", 0xFFB4CDBA);
        this.projectDao.insert(project);
        long projectId = project.getId();

        assertThat(projectId, equalTo(project.getId()));

        Task task = new Task(projectId, "tâche 1", new Date().getTime());

        this.taskDao.insert(task);
}

如果有人能帮忙就太好了,我不知道怎么解决。

非常感谢您的帮助

当您使用long projectId = project.getId();.

时,由于没有根据插入的值进行设置,项目id将为0

因此,当插入任务作为项目的 id 列时,外键冲突将由 SQLite 生成,并且不会为 0(它将为 1 或更大)。

改变

@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(Project project);

to(获取实际生成的id)

@Insert(onConflict = OnConflictStrategy.IGNORE)
long insert(Project project); // will return the id that has been generated 

然后使用 :-

    Project project = new Project("toto", 0xFFB4CDBA);
    long projectId = this.projectDao.insert(project); //<<<<< returns the actual id
    project.setId(projectId); // sets project id according to the inserted id BUT only if inserted and not ignored when returned value will be -1
    // You should really check for -1 and handle accordingly
   
    assertThat(projectId, equalTo(project.getId())); // not really of any use

    Task task = new Task(projectId, "tâche 1", new Date().getTime());
    this.taskDao.insert(task);
  • 注意,以上为in-principle代码,未编译或run/tested。因此它可能包含一些错误。