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

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

问题描述

我听说单元测试是完全真棒,真的很酷和各种各样的好东西,但70%或更多的我的文件涉及数据库访问(一些读和一些写)不知道如何写这些文件的单元测试。



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

解决方案

我建议嘲笑你的数据库调用。 Mocks基本上是对象,看起来像你试图调用一个方法的对象,在它们具有相同的属性,方法等可用于调用者的意义上。但是,当调用特定方法时,它不是执行它们被编程的任何动作,而是完全跳过,并且返回结果。这个结果通常由你提前定义。



为了设置你的对象进行嘲笑,你可能需要使用某种反转的控制/依赖注入模式,如下面的伪代码: / p>

  class Bar 
{
private FooDataProvider _dataProvider;

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

public getAllFoos(){
//而不是调用Foo.GetAll()在这里,我们引入一个额外的抽象层
return _dataProvider.GetAllFoos ();
}
}

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

现在在你的单元测试中,你创建一个模拟FooDataProvider,它允许你调用方法GetAllFoos而不必实际命中数据库。

  class BarTests 
{
public TestGetAllFoos(){
//这里我们设置我们的mock FooDataProvider
mockRepository = MockingFramework.new()
mockFooDataProvider = mockRepository.CreateMockOfType(FooDataProvider);

//创建一个新的Foo对象数组
testFooArray = new Foo [] {Foo.new(),Foo.new(),Foo.new()}

//下一条语句将导致每当我们调用FooDAtaProvider.GetAllFoos,
//时返回testFooArray,而不是调用数据库并返回任何内容
// ExpectCallTo和Returns是我们假想的模拟框架提供的方法
ExpectCallTo(mockFooDataProvider.GetAllFoos).Returns(testFooArray)

//现在开始我们的实际单元测试
testBar = new Bar(mockFooDataProvider)
baz = testBar.GetAllFoos()

// baz现在应该等于我们之前创建的testFooArray对象
Assert.AreEqual(3,baz.length)
}
}

一个常见的嘲笑场景。当然,你仍然可能想要单元测试你的实际数据库调用,你需要打到数据库。


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.

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

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天全站免登陆