2
votes

I am testing a DAO and in order to do so, I need to extend it with a getAll() method not existing in the production code.

The only way I could think about to achieve this, is to extend my database implementation with an extended DAO containing the getAll() I need. The code looks like the following:

@Database(
                entities = [
                    OneEntity::class,
                    AnotherEntity::class
                ],
                version = 1,
                exportSchema = false
        )
        abstract class TestDatabase : RoomDatabase() {
            abstract fun getOneEntityDao(): OneEntityDao
            abstract fun getAnotherEntityDao(): TestAnotherEntityDao
        }

@Dao
abstract class TestAnotherEntityDao : AnotherEntityDao {

        @Query("""select * from $ANOTHER_ENTITY_TABLE""")
        abstract fun getAll() : Single<List<AnotherEntity>>
    }

But when I run the tests I get the following error:

`java.lang.RuntimeException: cannot find implementation for com.example.persistence.TestDatabase. TestDatabase_Impl does not exist`

I already checked other answers and the only thing that worked for me is to move the Testdatabase class out of the test directory but I'd rather prefer not to have a test class in my production code. Any ideas why is this happening and how to solve it?

2
I ended up querying the database for a Cursor and checking if it contains the expected data object. No need of test code in the production code (no TestDatabase no test query in the DAO neither) - Eduardo

2 Answers

1
votes

Have you included all the necessary TestDepenedencies for the test build to recognize Room content as well as the kapt and other necessary components? I see what you are trying to do, haven't personally done it, but you are extending generated code, so that seems potentially unreliable.

Whats the reason you don't just add a "getAll" to the standard DAO class and just only use it in tests. If you are concerned about others' touching it, you could always throw a deprecated tag over it, but the interface that exposes it all would seem like a better place for this to live with more reliable access.

However, if you feel the query doesn't belong to either table, you could make a DAO specifically for your custom query needs. You can specify the query that the fun does. like

@Query ( "SELECT * FROM firstTable UNION SELECT * FROM secondTable")
fun myCombiningQueryMethod() : MyEntityArray

You aren't forced to query the content of your own table as far as I know. So write as nice of query as you want and make a class for it.

Then if you are worried about having that class in your production code, simply make a flavor. Split out the Database implementation, one flavor is for production and one is for testing where it includes the additional table.

Hope that helps. happy coding.

0
votes

Thank you for your answer Sam!

Regarding your comment

Have you included all the necessary TestDepenedencies for the test build to recognize Room content as well as the kapt and other necessary components?

-> Yes I did. As I wrote before, my problem is not related to the kapt or any lacking component since putting my TestDatabase in another folder out of my test folder path works and the TestDatabase_Impl is generated.

I am not extending generated code though, but replacing my database with a test in-memory one that provides access to extended DAOs with testing methods like getAll(). Since I am not testing how Room generates its components I think it is save enough to replace the database as long as I keep the DAOs.

As you pointed out, I don't have a query getAll() because I don't need it in my production code and I didn't want to create it for the sake of testing (in order to check if inserting in the database is working and be able to check the stored data for example)

For now I think I will do as you suggest and put a get method in my DAOs since I am not seeing another "fast" alternative, but I'll keep in mind your idea of using flavours and will try it in the nearest future.

Thanks!