首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用数据库查询对对象进行单元测试

如何使用数据库查询对对象进行单元测试
EN

Stack Overflow用户
提问于 2008-08-27 17:46:03
回答 10查看 89.9K关注 0票数 166

我听说单元测试“非常棒”,“真的很酷”,“各种各样的好东西”,但我的文件中有70%或更多涉及数据库访问(一些是读的,一些是写的),我不确定如何为这些文件编写单元测试。

我正在使用PHP和Python,但我认为这是一个适用于大多数/所有使用数据库访问的语言的问题。

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2008-08-27 18:30:47

我建议模拟你对数据库的调用。模拟基本上是看起来像你试图调用方法的对象的对象,从某种意义上说,它们具有相同的属性、方法等可供调用者使用。但是,当一个特定的方法被调用时,它不会执行它们被编程执行的任何操作,而是完全跳过这一步,只返回一个结果。这个结果通常是由你提前定义的。

为了将对象设置为模拟,您可能需要使用某种控制反转/依赖注入模式,如下面的伪代码所示:

class Bar
{
    private FooDataProvider _dataProvider;

    public instantiate(FooDataProvider dataProvider) {
        _dataProvider = dataProvider;
    }

    public getAllFoos() {
        // instead of calling Foo.GetAll() here, we are introducing an extra layer of abstraction
        return _dataProvider.GetAllFoos();
    }
}

class FooDataProvider
{
    public Foo[] GetAllFoos() {
        return Foo.GetAll();
    }
}

现在,在您的单元测试中,您将创建一个FooDataProvider模拟,它允许您在不必实际访问数据库的情况下调用方法GetAllFoos。

class BarTests
{
    public TestGetAllFoos() {
        // here we set up our mock FooDataProvider
        mockRepository = MockingFramework.new()
        mockFooDataProvider = mockRepository.CreateMockOfType(FooDataProvider);

        // create a new array of Foo objects
        testFooArray = new Foo[] {Foo.new(), Foo.new(), Foo.new()}

        // the next statement will cause testFooArray to be returned every time we call FooDAtaProvider.GetAllFoos,
        // instead of calling to the database and returning whatever is in there
        // ExpectCallTo and Returns are methods provided by our imaginary mocking framework
        ExpectCallTo(mockFooDataProvider.GetAllFoos).Returns(testFooArray)

        // now begins our actual unit test
        testBar = new Bar(mockFooDataProvider)
        baz = testBar.GetAllFoos()

        // baz should now equal the testFooArray object we created earlier
        Assert.AreEqual(3, baz.length)
    }
}

简单地说,这是一种常见的模仿场景。当然,您可能仍然希望对实际的数据库调用进行单元测试,为此,您需要访问数据库。

票数 88
EN

Stack Overflow用户

发布于 2008-08-27 18:14:54

对具有数据库访问权限的对象进行单元测试的最简单方法是使用事务作用域。

例如:

    [Test]
    [ExpectedException(typeof(NotFoundException))]
    public void DeleteAttendee() {

        using(TransactionScope scope = new TransactionScope()) {
            Attendee anAttendee = Attendee.Get(3);
            anAttendee.Delete();
            anAttendee.Save();

            //Try reloading. Instance should have been deleted.
            Attendee deletedAttendee = Attendee.Get(3);
        }
    }

这将恢复数据库的状态,基本上类似于事务回滚,因此您可以根据需要多次运行测试,而不会产生任何副作用。我们已经在大型项目中成功地使用了这种方法。我们的构建确实需要一点时间来运行(15分钟),但对于拥有1800个单元测试来说,这并不可怕。此外,如果构建时间是一个问题,您可以将构建过程更改为具有多个构建,一个用于构建src,另一个随后启动以处理单元测试、代码分析、打包等……

票数 13
EN

Stack Overflow用户

发布于 2008-08-27 17:49:28

如果您想要对您的类进行单元测试,您应该模拟数据库访问。毕竟,您不希望在单元测试中测试数据库。这将是一次集成测试。

将调用抽象出来,然后插入一个仅返回预期数据的mock。如果您的类除了执行查询之外并不能做更多的工作,那么测试它们可能就不值得了……

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30710

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档