如何使用数据库查询对对象进行单元测试 [英] How to unit test an object with database queries

查看:24
本文介绍了如何使用数据库查询对对象进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我听说单元测试非常棒"、非常酷"和各种各样的好东西",但我 70% 或更多的文件涉及数据库访问(一些读取和一些写入),我不确定如何为这些文件编写单元测试.

I've heard that unit testing is "totally awesome", "really cool" and "all manner of good things" but 70% or more of my files involve database access (some read and some write) and I'm not sure how to write a unit test for these files.

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

I'm using PHP and Python but I think it's a question that applies to most/all languages that use database access.

推荐答案

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

I would suggest mocking out your calls to the database. Mocks are basically objects that look like the object you are trying to call a method on, in the sense that they have the same properties, methods, etc. available to caller. But instead of performing whatever action they are programmed to do when a particular method is called, it skips that altogether, and just returns a result. That result is typically defined by you ahead of time.

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

In order to set up your objects for mocking, you probably need to use some sort of inversion of control/ dependency injection pattern, as in the following pseudo-code:

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 方法而无需实际访问数据库.

Now in your unit test, you create a mock of FooDataProvider, which allows you to call the method GetAllFoos without having to actually hit the database.

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)
    }
}

简而言之,一个常见的模拟场景.当然,您可能仍然希望对实际的数据库调用进行单元测试,为此您需要访问数据库.

A common mocking scenario, in a nutshell. Of course you will still probably want to unit test your actual database calls too, for which you will need to hit the database.

这篇关于如何使用数据库查询对对象进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆