简体   繁体   English

单元测试数据库交互器

[英]Unit testing database interactors

I have a database interaction component which has, amongst other things, a Writer and a Reader class. 我有一个数据库交互组件,除其他外,它具有Writer和Reader类。 The writer class has write methods such as insertEntity( Entity ) and updateEntity( Entity ), while the Reader has methods such as getEntityById( EntityId ). writer类具有write方法,例如insertEntity(Entity)和updateEntity(Entity),而Reader类具有诸如getEntityById(EntityId)的方法。

For implementing this component I'd like to use TDD as I usually do, though am unsure on how to manage this. 为了实现此组件,我不确定要如何管理它,但还是想像平常一样使用TDD。 If I start with implementing the Writer, how am I going to do meaningful asserts if I do not have the Reader methods yet. 如果我从实现Writer开始,如果还没有Reader方法,我将如何做有意义的断言。 And even if I had the Reader methods, I'd preferably not want to use them in the tests for the Writer, though perhaps this is wishful thinking. 即使我有Reader方法,我也最好不要在Writer的测试中使用它们,尽管这也许是一厢情愿的想法。

Testing such code seems inherently a pain as tables need to be setup and teared down. 测试这种代码本质上是一件痛苦的事情,因为需要设置和拆除表。 However since I have not tried to do TDD for such code before, I might be missing out on tricks to make this relatively painless. 但是,由于我之前从未尝试过对此类代码进行TDD,所以我可能会错过使它相对轻松的窍门。 Any pointers on that are appreciated. 对此的任何指示都值得赞赏。

You don't need a database for this as long as you have an abstraction in place. 只要有了适当的抽象,就不需要数据库。

For example if I made a method getEntityById , I could have a class which would use an in memory store (array, hash etc...). 例如,如果我使方法getEntityById ,我可以有一个将在内存中使用的类(数组,哈希等)。 While my production code would make use of a concrete instance. 虽然我的生产代码将使用具体实例。 In pseudo code: 用伪代码:

class MemoryStore
{
    getEntityById(id)
    {
       // Return hardcoded response or canned results
    }
}

class DatabaseStore
{
    getEntityById
    {
        // Go off to the real database and do reads.
    }
}

You can then write you tests without ever hitting a real database. 然后,您可以编写测试,而无需访问实际数据库。 Remember, if you do consume a third party service, API, DB, file system etc... you are not unit testing. 请记住,如果您确实使用了第三方服务,API,数据库,文件系统等,则不是单元测试。

The other benefit here is that you can have another developer working on the database access code, while you work on the rest of the application. 这里的另一个好处是,您可以在开发应用程序其余部分的同时,让另一个开发人员来处理数据库访问代码。 This all relies on "coding to an interface". 所有这些都依赖于“编码到接口”。

What if you want to test the database access code? 如果要测试数据库访问代码怎么办? Well you would want an integrated test. 好吧,您需要集成测试。 A real database would be used here and you can instantiate the code which read/writes to the database. 这里将使用真实的数据库,您可以实例化对数据库进行读/写的代码。 Naturally this would be slow and require seed data. 自然,这将很慢并且需要种子数据。 The point is you test these standalone, the rest of you app would use the in memory fakes. 关键是您要独立测试这些应用程序,其余的应用程序将使用内存中的伪造品。 So in the above example, as long as the DatabaseStore worked on its own, we could be confident the rest of the code did the right thing. 因此,在上面的示例中,只要DatabaseStore工作,我们就可以相信其余代码可以正确执行操作。

What I do is implement my CREATE methods first and I test these by querying the database directly and not through my DAO's READ methods. 我要做的是先实现我的CREATE方法,然后通过直接查询数据库而不是通过DAO的READ方法来测试它们。 When these pass you can write your READ tests using your CREATE methods to populate your database with test data and then implement your READ methods. 通过这些测试后,您可以使用CREATE方法编写READ测试,以用测试数据填充数据库,然后实现READ方法。

As far as setting up and tearing down the database after each test, place the SQL to do this in your set-up and teardown methods. 至于在每次测试后建立和拆除数据库,请将SQL做到这一点在您的建立和拆除方法中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM