Browse Source

Add first tests on MySQL datasource ( mock party ! )

A test on datasource __init__ method
A test on datasource insert method (for leobject inserts only) <= this test uses a lot of mocks and can maybe be factorised
Yann Weber 9 years ago
parent
commit
0e54a47399
2 changed files with 125 additions and 0 deletions
  1. 0
    0
      DataSource/test/__init__.py
  2. 125
    0
      DataSource/test/test_mysql_datasource.py

+ 0
- 0
DataSource/test/__init__.py View File


+ 125
- 0
DataSource/test/test_mysql_datasource.py View File

@@ -0,0 +1,125 @@
1
+"""
2
+    Tests for MySQL Datasource
3
+"""
4
+
5
+import random
6
+import copy
7
+
8
+import unittest
9
+import unittest.mock as mock
10
+from unittest import TestCase
11
+from unittest.mock import patch, Mock, call
12
+
13
+import mosql
14
+import mosql.db
15
+from mosql.util import Query as mosql_Query
16
+import pymysql
17
+
18
+import leapi.test.utils #Code generation functions
19
+
20
+import Lodel.settings
21
+import DataSource.MySQL
22
+from DataSource.MySQL.leapidatasource import LeDataSourceSQL as DataSource
23
+from DataSource.MySQL.common_utils import MySQL as db_utils
24
+from EditorialModel.classtypes import common_fields, relations_common_fields
25
+
26
+class DataSourceTestCase(TestCase):
27
+    #Dynamic code generation & import
28
+    @classmethod
29
+    def setUpClass(cls):
30
+        """ Write the generated code in a temporary directory and import it """
31
+        cls.tmpdir = leapi.test.utils.tmp_load_factory_code()
32
+    @classmethod
33
+    def tearDownClass(cls):
34
+        """ Remove the temporary directory created at class setup """
35
+        leapi.test.utils.cleanup(cls.tmpdir)
36
+
37
+    def test_init(self):
38
+        """ Test __init__ for datasource """
39
+        with patch.object(mosql.db.Database, '__init__', return_value=None) as mock_db:
40
+            #Test __init__ without arguments
41
+            DataSource()
42
+            conn_args = db_utils.connections['default']
43
+            db_module = conn_args['module']
44
+            del(conn_args['module'])
45
+            mock_db.assert_called_once_with(db_module, **conn_args)
46
+
47
+            mock_db.reset_mock()
48
+            #test with arguments
49
+            conn_args = { 'hello': 'world', 'answer': 42 }
50
+            DataSource(mosql, conn_args)
51
+            mock_db.assert_called_once_with(mosql, **conn_args)
52
+
53
+            mock_db.reset_mock()
54
+
55
+            DataSource(conn_args = conn_args)
56
+            mock_db.assert_called_once_with(pymysql, **conn_args)
57
+    
58
+    def test_insert_leobject(self):
59
+        """ Test the insert method on LeObjects """
60
+        from dyncode import Article, Personne, Rubrique
61
+
62
+        for letype in [Article, Personne, Rubrique]:
63
+            lodel_id = random.randint(0,4096) # Choose a random lodel_id
64
+            
65
+            # Mock the cursor to superseed the lastrowid property
66
+            cursor_mock = Mock()
67
+            cursor_mock.lastrowid = lodel_id
68
+            # Mock the cursor() call on connection
69
+            cursor_call_mock = Mock(return_value=cursor_mock)
70
+            # Mock the connection to set the cursor() call mock
71
+            connection_mock = Mock()
72
+            connection_mock.cursor = cursor_call_mock
73
+            # Mock the connect() call on dbmodule to bla bla
74
+            connect_call_mock = Mock(return_value=connection_mock)
75
+            # Mock the db module to set the connection mock (on connect() call)
76
+            dbmodule_mock = Mock()
77
+            dbmodule_mock.connect = connect_call_mock
78
+
79
+            datasource = DataSource(module=dbmodule_mock, conn_args = {})
80
+
81
+            sql_query = 'SELECT wow FROM splendid_table'
82
+
83
+            class_table_datas = { 'title': 'foo', 'number': 42 }
84
+            object_table_datas = { 'string': random.randint(-42,42) }
85
+            
86
+            # build the insert datas argument
87
+            insert_datas = copy.copy(object_table_datas)
88
+            insert_datas.update(class_table_datas)
89
+
90
+            with patch.object(mosql_Query, '__call__', return_value=sql_query) as mock_insert:
91
+                with patch.object(db_utils, 'query', return_value=cursor_mock) as mock_utils_query:
92
+                    #mock_utils_query = Mock()
93
+                    #db_utils.query = mock_utils_query
94
+
95
+                    # call the insert() method
96
+                    datasource.insert(letype, **insert_datas)
97
+
98
+                    # construct expected datas for object table insert
99
+                    object_table_datas['class_id'] = letype._class_id
100
+                    object_table_datas['type_id'] = letype._type_id
101
+                    # construct expected datas used in class table insert
102
+                    class_table_datas['lodel_id'] = lodel_id
103
+
104
+                    expected_calls = [
105
+                        # insert in object table call
106
+                        call(
107
+                            db_utils.objects_table_name,
108
+                            object_table_datas
109
+                        ),
110
+                        # insert in class specific table call
111
+                        call(
112
+                            db_utils.get_table_name_from_class(letype._leclass.__name__),
113
+                            class_table_datas
114
+                        ),
115
+                    ]
116
+
117
+                    expected_utils_query_calls = [
118
+                        call(datasource.connection, sql_query),
119
+                        call(datasource.connection, sql_query),
120
+                    ]
121
+
122
+                    mock_insert.assert_has_calls(expected_calls, any_order = False)
123
+                    mock_utils_query.assert_has_calls(expected_utils_query_calls)
124
+
125
+

Loading…
Cancel
Save