模拟__init __()进行单元测试

23 python sqlite unit-testing mocking

我有一节课:

class DatabaseThing():
     def __init__(self, dbName, user, password):
          self.connection = ibm_db_dbi.connect(dbName, user, password)
Run Code Online (Sandbox Code Playgroud)

我想测试这个类但是测试数据库.所以在我的测试课中,我是这样的:

import sqlite3 as lite
import unittest
from DatabaseThing import *

class DatabaseThingTestCase(unittest.TestCase):

    def setUp(self):
        self.connection = lite.connect(":memory:")
        self.cur = self.connection.cursor()
        self.cur.executescript ('''CREATE TABLE APPLE (VERSION INT, AMNT SMALLINT);
            INSERT INTO APPLE VALUES(16,0);
            INSERT INTO APPLE VALUES(17,5);
            INSERT INTO APPLE VALUES(18,1);
            INSERT INTO APPLE VALUES(19,15);
            INSERT INTO APPLE VALUES(20,20);
            INSERT INTO APPLE VALUES(21,25);''')
Run Code Online (Sandbox Code Playgroud)

我将如何使用此连接而不是我要测试的类的连接?意味着使用连接setUp(self)而不是连接DatabaseThing.我无法在不实例化类的情况下测试函数.我想__init__在Test Class中以某种方式模拟该方法,但我没有找到任何在文档中看起来有用的东西.

Mar*_*ers 38

您可以简单地将数据库类子类化并对其进行测试,而不是模拟:

class TestingDatabaseThing(DatabaseThing):
     def __init__(self, connection):
          self.connection = connection
Run Code Online (Sandbox Code Playgroud)

并实例类,而不是DatabaseThing为你的测试.方法仍然相同,行为仍然是相同的,但现在所有使用的方法都使用self.connection测试提供的连接.

  • @information_interchange:测试什么时候*不*依赖于被测试的东西? (4认同)

mau*_*777 26

如果您想在初始化类时返回模拟,请模拟 __new__ 方法,而不是init

new创建新实例,init对其进行初始化,但只能返回 None。

如果您模拟new,它可以返回一个模拟,您可以在其上断言以模拟测试中的实例创建。

@mock.patch('Car.__new__')
def test_create_car(self, mock_Car):
    mock_inst = mock.MagickMock()
    mock_Car.return_value = mock_inst

    create_car()

    # Assert class was called
    mock_Car.assert_called_once()
    # __new__ is called with actual class as first arg
    mock_Car.assert_called_with(Car) 

    # Assert instance method is called as expected
    mock_inst.set_miles.assert_called_with(0)
Run Code Online (Sandbox Code Playgroud)


Jul*_*ins 6

您应该使用mockpackage 来模拟__init__类的方法:

from mock import patch


def test_database_thing(self):
    def __init__(self, dbName, user, password):
        # do something else
    with patch.object(DatabaseThing, '__init__', __init__):
        # assert something

Run Code Online (Sandbox Code Playgroud)

  • 虽然此代码片段可能是解决方案,但包括解释确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而那些人可能不知道您提出代码建议的原因。 (2认同)

Jam*_*Lim 5

控制反转

长期解决方案是让客户端创建连接并将其移交给DatabaseThing使用。使用单一职责原则,我认为DatabaseThing在这种情况下不应该负责建立连接。

这种技术减少了依赖性并为您提供了更大的灵活性,例如您可以设置一个连接池并DatabaseThing为池中的每个新连接实例提供连接,而无需更改DatabaseThing.