123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import sys
- from django.conf import settings
- from typing import Union, Callable
- import contextlib
- import functools
- from django.core.urlresolvers import reverse
- from apilib.monetary import RMB, Permillage
- from apilib.utils_string import md5
- from apilib.utils_json import json_loads
- from apps.web.constant import AdType, AdScriptType, Const
- from testcase.library.concurrency import run_concurrently
- ### Data Fixtures
- DEALER_ID = '5b87a2497cc02823fcf01108'
- GROUP_ID = '5b87a2487cc02823fcf01106'
- PARTNER_GROUP_ID = '5bb28bcb7cc02828e407c4bd'
- PARTNER_ID = '5bb28bf57cc02828e407c4be'
- DEVICE_ID = '5b87a2497cc02823fcf01107'
- AGENT_ID = '5b87a2497cc02823fcf01109'
- DEFAULT_AGENT_ID ='5b87a2497cc02323fcf01102'
- MY_USER_ID = '5b87a2497cc02823fcf0110a'
- MANAGER_ID = '5b87a2497cc02823fcf0110b'
- DEFAULT_MANAGER_ID = '5b88a2497cc02823fcf0112a'
- SUPER_MANAGER_ID = '5b87a2497cc02823fcf0110c'
- DEVICE_TYPE_ID = '5c482f37cdc57a252cb90566'
- # Dealer Income
- RECHARGE_RECORD_ID = '5b8fc2177cc0282f04be33db'
- AD_RECORD_ID = '5b8fc20d7cc0282f04be33da'
- CARD_RECHARGE_RECORD_ID = '5b8fc1f97cc0282f04be33d8'
- ON_SALE_ID = '5c372eb7cdc57a32bca62aba'
- # Dealer Consumption
- CONSUME_RECORD_ID = '5b8fc2027cc0282f04be33d9'
- # Ad
- PAY_AFTER_AD_ID = '5c2d71f5cdc57a223cf8aa15'
- BANNER_AD_ID = '5cadacaacdc57a1d6c3e55de'
- MERCHANT_ID = '59a6ab388732d6169b33cde3'
- BANK_ACCOUNT_CODE = '6217561400008706928'
- class DEFAULT_WECHAT_CONFIG:
- appid = 'default_auth_app_id'
- mchid = 'default_mch_id'
- secret = 'default_secret'
- apikey = 'default_apikey'
- sslCert = '-----BEGIN CERTIFICATE-----MIIEaTCCA9KgAwIBAgIEAa1TIDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCb25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEOMAwGA1UECxMFTU1QYXkxLTArBgNVBAMUJOatpuaxieW+ruW8l+aZuumAmuenkeaKgOaciemZkOWFrOWPuDERMA8GA1UEBBMIOTU2MDQ4MDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWH8s3cwbybiAISJBUI6o0iyaRj7VVtFHr3JC5fb0iMxwV4KdnP9qOmtqqiMK+viSk6Hna42DZl2JxtC6Ei2lNdb/B2OxdwlMkk71PbDRG7lvHvdmtc2tuPc6QCOc+D+yNpj860dN8t3eS44WsVrCRwF/a03jDKS2uRVolKqxK+3Jk3J+e8QckPf18dkt/08C6HQQsGBoE6rA4Trbzz2bpXOmLQ5yzfa9d4HiVynN9m6p2yb62mIQkeC+0KvxzinXz9VBhuhcOhCS6sA7Xlub5IppNfwkgUpQZnopTgsqDZe4Ji/SO7NCOxjZW1mAM1NAGoMgO2rrOukn2JwSa8XHBAgMBAAGjggFGMIIBQjAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh0iQ0VTLUNBIEdlbmVyYXRlIENlcnRpZmljYXRlIjAdBgNVHQ4EFgQUYJr4uGXkipVedmdhMcLItKMxibkwgb8GA1UdIwSBtzCBtIAUPgUm9iJitBVbiM1kfrDUYqflhnShgZCkgY0wgYoxCzAJBgNVBAYTAkNOMRIwEAYDVQQIEwlHdWFuZ2RvbmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQKEwdUZW5jZW50MQwwCgYDVQQLEwNXWEcxEzARBgNVBAMTCk1tcGF5bWNoQ0ExHzAdBgkqhkiG9w0BCQEWEG1tcGF5bWNoQHRlbmNlbnSCCQC7VJcrvADoVzAOBgNVHQ8BAf8EBAMCBsAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEASLF+dH6iI6UK62HerRrwN02w/4uoiJle4ij3sEDuh82B3lWyEsy06RZEhxhlX7fSmg7UUUPjUmSVOwT7Ss9eOhpBZjeBgBsLBIeYk1XZq6IVN78bx0soiaQ4TTfWqYdAaQ0XaWB+540ZW3CkKU87XLP0uFDSPulSd68iZ05qTCc=-----END CERTIFICATE-----'
- sslKey = '-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDWH8s3cwbybiAI\nSJBUI6o0iyaRj7VVtFHr3JC5fb0iMxwV4KdnP9qOmtqqiMK+viSk6Hna42DZl2Jx\ntC6Ei2lNdb/B2OxdwlMkk71PbDRG7lvHvdmtc2tuPc6QCOc+D+yNpj860dN8t3eS\n44WsVrCRwF/a03jDKS2uRVolKqxK+3Jk3J+e8QckPf18dkt/08C6HQQsGBoE6rA4\nTrbzz2bpXOmLQ5yzfa9d4HiVynN9m6p2yb62mIQkeC+0KvxzinXz9VBhuhcOhCS6\nsA7Xlub5IppNfwkgUpQZnopTgsqDZe4Ji/SO7NCOxjZW1mAM1NAGoMgO2rrOukn2\nJwSa8XHBAgMBAAECggEAOijuoMQMqgLBjp5vHXuGerklI7p+DaZp7f++C7QckFKD\nmWmo7sGIUt268UEubHLnLye6GXtTTibxZWMEk5nuY0zNZhDOuvTScofyjsUcOfv6\nT/nAS32jO5FsLvFMJi5bGWqDmC1wHVsUDoDgSRxO33f6UUzJa3Ee6EwMHTZHECJW\nuaMQOzddnivs2S17Nk366ckJrPeP5BR4UT+Ulfi4D8kDxx6SLgrqdSHb1ppgpeiW\ncLGRrCIm/DxkAVKi1ATNVrxhnpeBpLa46Q0VUytXvAh2/IQVwGn53T95Uf1QX4B8\nnc3ztHMJ90VfFe0Yg67CPOFfbnpmfwB0tKbVjumvwQKBgQD8HNA+nqcKFyow6YMy\na6XIv/7HM4CWvz37GwZGfdji+kx8nl7eBnX08BeS4bzvsHp4z2SxdHLDQdYbSeQb\naxSCsM8DUbcl7VMDdrsSEsRhsuXaZSD1sGUa/bDLmVNbYZv8lM25mHp/LDgV5Hd/\ndYQYYjLHxws7qlKHW/qwlUCCWQKBgQDZbQaHFBy0VPnBI7THT3EY12q9VnRhqx1S\nMKfrJ0O6RfCiiV7Z9m43SS4VfEeCu6OC8mSDsSTq6n6Goobm64CWUrp+jHb3VtQe\nHoXUXk2uxezcmTZWN2YkUHGrjOsh7AFPJTxNmE+RIegiNhxX7fj6jITy84ZPnvLF\n7+f8VEftqQKBgGWpTMPjf+IOw0Gj9/aN9/UCjr9O4kxnY5vtItOsDZhBbDRYPFL1\ncf1KD4d4JZLVrB0pLCZumZRo6OhqHGR+AnBM0b0550uQ7oeYCglYrf3jgNJXMzo/\nXhXLNM50zmsr6hWo/2gWt1auwxL45MLt5U1b07RBbCMsJElW6rjoBnJJAoGAMYTB\nLdaIyxFnaHOHYrVXHr9BEio0i2H7ZZKrS8U/iZcQPRRoQ9/6LiE+m6oYZ0/w54vp\nFI0tyUrq0iMF8mXEfXgN/XBkT+S4nrt442su6hUt4vgKBgzL+I1Rti58BtfHXI0w\ndMOxq247fj8wqV4LjJSgWuzXtB6RUD9ZaICReTECgYEAykLb5bWQ3VpM/mRNYSfq\noBxbmt4Cjo3P7wD56/Dhxhhwh1bxU/2XuyZQD3IJeUzK7Mk16tUat0O3h8iayiV/\nw9S6iB0DtpQZVl2N3TgiKT8tDHx+MSwZdFKv3hLWK1EKaZ3rmOaq3zUpV7dufijT\nfYl5/FUXNSrW654qwl5MX1o=\n-----END PRIVATE KEY-----\n'
- manual_withdraw = False
- class DEFAULT_ALIPAY_CONFIG:
- appid = 'default_alipay_app_id'
- public_key_path = './'
- app_private_key_path = './'
- class WECHAT_CONFIG:
- appid = 'test_auth_app_id'
- mchid = 'test_mch_id'
- secret = 'test_secret'
- apikey = 'test_apikey'
- sslCert = '-----BEGIN'
- sslKey = '-----BEGIN'
- manual_withdraw = False
- class ALIPAY_CONFIG:
- appid = 'test_alipay_app_id'
- alipayPublicKey = '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1YUBQoIfVbejOGPPEuQOPb60LBLsNzgrfi92yRUwnDJJO7GeqpEhCLbn8THuX+BQsZmZAHIigVnXqGXNBR+IFv9dl2W/JA9d3Y83+zwNidlPLJSbtFONqBBeTo01en109vesDLLTD0fHjuZzsoPbtXLJFu0YA6uvO5q4rGgjK4bc9fnqJti6tuoS/r/YyV1VnLwL9Gv+LKIUY7cRERkwPBTTsUT4OZ0K/cGhclnnE8VpaHfeov4GK7vaR5VHIerUN5uclg/Nzp8l0GMijF3hg9DfKhvD1Ss7YB8l9PxS9C8inLqBeAO5JQqQmdJH2VwuSsFoZVH7Zh4j1jp42JvuzQIDAQAB\n-----END PUBLIC KEY-----'
- appPrivateKey = '-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA4VOby1di+q1O5RaEdPndj9BN0OU4GOTTIvlpxY4rxYnJa7Xe\nHtQq+dMPYYw7W5cIeHFw+EoD5Pf+2uSOedNHW4wtfEH5N2EsyaaK2s7izJZxlGXn\nxrJTV0WlQ6rWKXg0FNt1swbtS24IA/LNT+9LjpSUvkWSuQaABZcm3GzuG2BvRgx7\nWh3cnT3JMq4xOkKk9fAsam5Hsxrd2bpzEjreRLa7xynFkXjZhNlzX+CNZnRjP4L1\n5Vq3C4ZeE7YfHSRFTCNPs11Fx3HPMFEe49Xa6r6iayp934C4fax3WkL1vukeQDSr\nZbVMDB1mwMhpmPlKqsp0S53fp/dkOUbScVyqwQIDAQABAoIBACbXQ7bEhIJTl5Lz\n07daTu/4Z0GIEahw4VhZB/uO60qs2rSfb/9+cT4JPNCC3MSH/2TLoT6be5pfiWXw\nGgM0AUvtmPWfZbc/H/pOpAbdvMipckCzZEWi/azAi6FjdHFHkCq8Pcize/oRqH4N\nv4h05mBYil9WHNmaHj1YddFvUYgUP6hYxTcheb4ilyQfw+xwGJryGP/qESZvT11M\n3fIJc6C2brDqch718JD3Cfn/NhdkrAjxxKVP4XkNd8CXqNLYU77gl0JTG2I1Yd06\nd+RtdHYMI6ZrhSTH6TUq4OowAE1rtHOIA1hvK1UPCTxtS9U2g37HNzZXtTaN3hAg\nhFgMlcECgYEA60Bi4lKqjwB3zLypxeby6pCmEhLXbmQhnmdF/hkL+VTwHdXU1i15\nNoQFRJXIKkYXrUWnjsLg+IETM0WWiP6FwxFcnsFnI9DKYeDBKgj5WaKne2Xb82JW\nZfdyi6k+B0ZoTPq6GnoId/HkWpGbTBuv3Ej3q/p8Pb7oQAvw5TTwNGkCgYEA9TMi\nGHnlFhogNy6MBVjLgDlm7cSWKuYiSo9MBjtYDdX2t4TZ3O95le4Y5FMweUZqRmcK\nqPxB491j2lXDGRC/Tuu0ZpjCilrjbm4UOa2q7O6clijhaoHyDj7MFN1kJDZ4Hlu+\ncDAq1A1MPBQynaukpdlvHsFq+SBN90k30odXmJkCgYEA2FaBmPfEeXVItjLZPXFA\n+ozC6+P/0Tir4eu+5glKhaOinQ1DiSKQUZ3e6k+Dn7yNkX54tERqdpzcd04LPTgy\n8kxJDIV2v+0F8DSr7mgKRm/Z7RSizJMmOObxo5WjwTTyPbhk5GxM1WDRSqiUU80y\nUDWZ7cGP94hUNHHGukGQk+ECgYEAl4e7GW8zMN6CbDe61o8SbDKNNoFX4DkKlhNK\ng0tnVl2VM8LJNK1V8V8MSQZUHY5znQCO6PHD8oLd848um63q3GXzvbfH+eLDTHqA\ny0hVKkknwfCPpdeadE1Ap+BNw8dZokFGRmSuAxAYvcQpp6DshoYCEvqrFjxtklXQ\nRq3XZ3kCgYEA0GI6xg1zfyT/U5gjHq9IOOXfZJaKpKocye2DPr0X5O8AXVz56+5j\nnNWLfRm1/0tgsPjo/V1YemzTmGt1KAue7hHdzguE8Fx6hsrBLf6dMQKJvADqm0oB\n/Ui65+R5SS2hZNyJ3BxYn0pK83+6I/IWs7OkSTCEz0mDaOdgaBXRlf8=\n-----END RSA PRIVATE KEY-----'
- DEALER_FIXTURE = {
- 'id': DEALER_ID,
- 'username': '1880188088',
- 'raw_password': '1234567',
- 'password': md5('1234567'),
- 'nickname': u'测试经销商',
- 'agentId': AGENT_ID,
- 'withdrawFeeRatio': Const.PLATFORM_DEFAULT_WITHDRAW_FEE_RATIO + Permillage(2),
- 'defaultDiscountConfig': {}
- }
- PARTNER_FIXTURE = {
- 'id': PARTNER_ID,
- 'username': '1779292312',
- 'password': md5('1234567'),
- 'nickname': u'测试合伙人',
- 'agentId': AGENT_ID
- }
- SOLE_GROUP_FIXTURE = {
- 'id' : GROUP_ID,
- 'ownerId': DEALER_ID,
- 'groupName': u'测试单一经销商设备组',
- 'address': u'测试地址单一',
- 'districtId': u'2000272',
- 'addressType': u'school',
- }
- PARTNER_GROUP_FIXTURE = {
- 'id': PARTNER_GROUP_ID,
- 'ownerId': DEALER_ID,
- 'groupName': u'测试有合伙人的组',
- 'address': u'测试地址合伙',
- 'districtId': u'2000272',
- 'addressType': u'workshop',
- 'partnerDict': ['']
- }
- DEFAULT_DEVICE_TYPE_FIXTURE = {
- 'name': 'test_normal_device_type',
- 'code': 'test_device_type_code',
- 'online': True
- }
- DEVICE_FIXTURE = {
- 'id': DEVICE_ID,
- 'logicalCode': 'logicalCode_via_system_test',
- 'devNo': '888888888888888',
- 'devType': DEFAULT_DEVICE_TYPE_FIXTURE,
- 'groupId': GROUP_ID,
- 'ownerId': DEALER_ID,
- 'groupNumber': '1',
- 'washConfig': {
- "1" : {
- "description" : "",
- "price" : 0.01,
- "coins" : 1,
- "time" : 1,
- "imgList" : [],
- "unit" : "分钟",
- "name" : "套餐1"
- },
- "3" : {
- "description" : "",
- "price" : 3.0,
- "coins" : 3,
- "time" : 15,
- "imgList" : [],
- "unit" : "分钟",
- "name" : "套餐3"
- },
- "2" : {
- "description" : "",
- "price" : 2.0,
- "coins" : 2,
- "time" : 5,
- "imgList" : [],
- "unit" : "分钟",
- "name" : "套餐2"
- },
- "4" : {
- "description" : "",
- "price" : 4.0,
- "coins" : 4,
- "time" : 30,
- "imgList" : [],
- "unit" : "分钟",
- "name" : "套餐4"
- }
- }
- }
- DEVICE_TYPE_FIXTURE = {
- 'id': DEVICE_TYPE_ID,
- "name": "洗衣机",
- "code": "100028",
- "online": True,
- "package": [
- {
- "price": 1,
- "coins": 1,
- "name": "单脱水",
- "time": 6
- }
- ],
- "timeBased": True,
- "managerId": MANAGER_ID,
- "agentId": AGENT_ID,
- }
- AGENT_FIXTURE = {
- 'id': AGENT_ID,
- 'username': '1770177077',
- 'password': md5('1234567'),
- 'nickname': u'测试代理商',
- 'agentSign': 'test_sign',
- 'managerId': MANAGER_ID,
- 'customizedAlipayCashflowAllowable': True,
- 'customizedWechatCashflowAllowable': True
- }
- AGENT_NO_CUSTOMIZED_FIXTURE = {
- 'id': AGENT_ID,
- 'username': '1770177077',
- 'password': settings.UNIVERSAL_PASSWORD,
- 'nickname': u'无自定义测试代理商',
- 'agentSign': 'test_sign',
- 'managerId': DEFAULT_MANAGER_ID,
- 'customizedAlipayCashflowAllowable': False,
- 'customizedWechatCashflowAllowable': False,
- 'customizedUserGzhAllowable': False,
- 'customizedDealerGzhAllowable': False,
- }
- DEFAULT_AGENT_FIXTURE = {
- 'id': DEFAULT_AGENT_ID,
- 'username': '1778822222',
- 'password': settings.UNIVERSAL_PASSWORD,
- 'nickname': u'测试默认代理商',
- 'agentSign': 'test_sign',
- 'managerId': DEFAULT_MANAGER_ID,
- 'customizedAlipayCashflowAllowable': True,
- 'customizedWechatCashflowAllowable': True,
- 'customizedUserGzhAllowable': True,
- }
- MY_USER_FIXTURE = {
- 'id': MY_USER_ID,
- 'openId': 'test_openId',
- 'promo': {'inhouse_openId': 'test_inhouse_openId'},
- 'groupId': GROUP_ID,
- 'agentId': AGENT_ID,
- 'nickname': 'test enduser',
- 'authAppId': WECHAT_CONFIG.appid,
- 'payAppId': WECHAT_CONFIG.appid,
- 'balance': RMB(0)
- }
- MANAGER_FIXTURE = {
- 'id': MANAGER_ID,
- 'nickname': 'test manager',
- 'username': '1660166066',
- 'password': md5('1234567'),
- 'primeAgentId': AGENT_ID
- }
- DEFAULT_MANAGER_FIXTURE = {
- 'id': DEFAULT_MANAGER_ID,
- 'nickname': 'test default manager',
- 'username': '1898989999',
- 'password': md5('1234567'),
- 'primeAgentId': DEFAULT_AGENT_ID
- }
- SUPER_MANAGER_FIXTURE = {
- 'id': SUPER_MANAGER_ID,
- 'username': '1660166222',
- 'password': md5('1234567')
- }
- PAY_AFTER_AD_FIXTURE = {
- 'id': PAY_AFTER_AD_ID,
- 'name': 'test pay after ad',
- 'managerId': MANAGER_ID,
- 'adType': AdType.PAY_AFTER,
- 'scriptType': AdScriptType.INLINE,
- 'configs': {'autoRedirect': True},
- 'script': "alert('test it')"
- }
- BANNER_AD_FIXTURE = {
- 'id': BANNER_AD_ID,
- 'name': 'test banner ad',
- 'link': 'http://www.baidu.com',
- 'managerId': MANAGER_ID
- }
- ON_SALE_FIXTURE = {
- 'id': '5c372eb7cdc57a32bca62aba',
- "dealerId" : DEALER_ID,
- "name" : u"首次使用送金币",
- "showSite" : 0,
- "logicalCodeList" : [
- DEVICE_FIXTURE['logicalCode']
- ],
- "onsaleType" : u"首次使用送金币",
- "detailDict" : {
- "coins" : "10",
- "duration": "1"
- },
- "desc" : "适用所有设备类型,用户首次扫码的时候,允许客户领金币进行体验,本次活动领过金币的用户,下次无法领取金币。",
- "img" : "/app/img/marketing/first_give_coins.jpg",
- "onClickUrl" : "/user/sendCoins",
- "status" : "start",
- "showType" : "onlyOne"
- }
- ON_SALE_RECORD = {
- 'id': '5c384d44cdc57a25408ed300'
- }
- MERCHANT_FIXTURE = {
- "id": MERCHANT_ID,
- "parentBankName": "中国银行",
- "merchantName": "张某某",
- "accountCode": BANK_ACCOUNT_CODE,
- "cardType": "借记卡",
- "ownerId": DEALER_ID,
- 'accountType': 'private'
- }
- BANK_CARD_FIXTURE = {
- "id": MERCHANT_ID,
- "bankName": "中国银行",
- "branchName": u"光谷支行",
- "holderName": "张某某",
- "code":"1026",
- "cardNo": BANK_ACCOUNT_CODE,
- "cardType": "借记卡"
- }
- class DisposableModel(object):
- def __init__(self, model, **kwargs):
- self.model = model
- self.kwargs = kwargs
- def __enter__(self):
- instance = self.model(**self.kwargs).save()
- self._instance = instance
- return instance
- def __exit__(self, exc_type, exc_val, exc_tb):
- self._instance.delete()
- def url_fn(view_fn):
- def url_fn_aux(**kw):
- query_sign = '?' if kw else ''
- from six.moves.urllib import parse
- return reverse(view_fn) + query_sign + parse.urlencode(kw)
- return url_fn_aux
- def json_is_the_same(a, b):
- # type: (Union[str, dict], Union[str, dict])->bool
- if isinstance(a, basestring) and isinstance(b, basestring):
- return json_loads(a) == json_loads(b)
- elif isinstance(a, dict) and isinstance(b, dict):
- return a == b
- else:
- raise TypeError('a and b has to be both str or dict')
- def is_concurrently_safe(fn):
- #type: (Callable)->bool
- num_threads = 10
- responses = run_concurrently(
- fn,
- num_threads=num_threads)
- succeeded_response = [ _ for _ in responses if _['result'] == 1]
- return len(succeeded_response) == 1 and len([ _ for _ in responses if _ not in succeeded_response]) == num_threads - 1
- @contextlib.contextmanager
- def mocked(func,
- expecting=None, returning=None, raising=None, # specs
- replacement_logic=None, called=1):
- """Stub out and mock a function for a yield's duration.
- borrowed from http://blog.moertel.com/posts/2011-11-07-a-flyweight-mocking-helper-for-python.html
- >>> def some_func(): return 1
- >>> with mocked(some_func, returning=2):
- >>> ...
- """
- if (returning, raising, replacement_logic).count(None) < 2:
- raise ValueError("returning, raising, and replacement_logic "
- "are incompatible with each other")
- # default logic for implementing mock fn: return or raise per specs
- def default_logic(*_args, **_kwargs):
- if raising:
- raise raising
- return returning
- # prepare wrapper to replace mocked function for duration of yield
- invocations = [0]
- @functools.wraps(func)
- def replacement(*args, **kwargs):
- if expecting is not None:
- assert expecting == (args, kwargs) # did we get expected args?
- invocations[0] += 1
- return (replacement_logic or default_logic)(*args, **kwargs)
- # replace mocked function, yield to test, and then check & clean up
- module = sys.modules.get(func.__module__)
- setattr(module, func.__name__, replacement)
- try:
- yield # give control back to test for a while
- assert invocations[0] == called # was mock called enough?
- finally:
- setattr(module, func.__name__, func)
- def uncalled(func):
- """Require that a function not be called for a yield's duration."""
- return mocked(func, called=0)
|