unittest async mocks doesnt't work with pytest? - unit-testing

async def test_coro(id):
print("pass")
async def test_coro2():
print("pass")
async def mock_test_coro(id):
print("pass")
async def mock_test_coro2():
print("hj")
class Test(AioHTTPTestCase):
async def get_application(self):
app = web.Application(debug=True)
return app
#unittest_run_loop
#patch(__name__ + '.test_coro', side_effect=(lambda id: mock_test_coro(id)))
#patch(__name__ + '.test_coro2', side_effect=(lambda: mock_test_coro2()))
async def test_1(self, test_coro, test_coro2):
await test_coro2()
await test_coro(0)
I have fail in this test because (no parameter)
> test_coro = <AsyncMock name='test_coro2' id='139942609979472'>
> test_coro2 = <AsyncMock name='test_coro' id='139942609417456'>
why it so? (if there are more than 2 mocks - it shuffles they in random order)
for sync functions it was working fine

important is patch applying order,
last argument is patch on the top and first is patch at the bottomn
#unittest_run_loop
#patch(__name__ + '.test_coro2', side_effect=(lambda: mock_test_coro2()))
#patch(__name__ + '.test_coro', side_effect=(lambda id: mock_test_coro(id)))
async def test_1(self, test_coro, test_coro2):
await test_coro2()
await test_coro(0)

Related

Why is flask jsonify returning unidentified?

I am using fetch on the frontend to send data to my flask backend in order to make a movie seat booking. The whole process works fine until the client awaits the response, which is "undefined" . So , basically the database saves the data , the only problem is the response which is sent to the client. I used jsonify which usually works fine. Can anybody tell me what I am missing? Thanks in advance.
Here is the JS code :
function sendReservationToServer() {
const selectedSeats = sessionStorage.getItem('selectedSeats')
const reservation = { userId, selectedSeats, showTimeId, movieHallId }
fetch('/bookSeats', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(reservation)
}).then(response => {
response.json()
}).then(data => {
theatreHall.innerHTML = `${data} <br> <a href='/home'>Back to main menu</a>`
console.log(`${data}`)
}).catch(err => infoMsg.textContent = err)
sessionStorage.clear()
}
And this is the flask controller which handles the request:
#app.route("/bookSeats", methods=["POST"])
def book_seats():
selected_seats = request.json
user_id = selected_seats.get('userId')
seats = json.loads(selected_seats.get('selectedSeats'))
movie_hall_id = selected_seats.get('movieHallId')
seat_ids = []
showtime_id = selected_seats.get('showTimeId')
for seat in seats:
seat_ids.append(db.session.query(Seat).filter(
Seat.seat_number == seat).filter(Seat.movie_hall_id == movie_hall_id).all()[0].stid)
for seat in seat_ids:
reserved_seat = ReservedSeat(
seat_id=seat, show_time=showtime_id, user=user_id)
db.session.add(reserved_seat)
db.session.commit()
reservation = Reservation(
user=user_id, show_time=showtime_id, number_of_tickets=len(seat_ids))
db.session.add(reservation)
db.session.commit()
message = f'{seats} booked successfully'
return jsonify(message)
data is undefined because the first then does not return anything. Either make it return response.json() or move everything in the second then to the first and replace data with response.json().

JsonWebsocketConsumer class self.send() in a loop sends all the iterations messages at once

when I use self.send(content) in a loop , all the messages are sent at once , instead of one my one.
the first self.send() in the if condition od connecting is executed perfectly
but all loop self.send() messages are recieved by client at once after a delay of about 60 second. how to make it one at a time?
consumer.py
from channels.generic.websockets import JsonWebsocketConsumer
class MyConsumer(JsonWebsocketConsumer):
# Set to True if you want it, else leave it out
strict_ordering = False
def connect(self, message, **kwargs):
super(MyConsumer,self).connect(message)
pass
def receive(self, content, **kwargs):
if content['status'] == "connecting":
content['status'] = "connected"
self.send(content)
elif content['status'] == "data":
for p in range(5):
content={
'status': 'sending',
'polygon': p
}
self.send(content)
time.sleep(15)
self.close()
def disconnect(self, message, **kwargs):
pass
clientside.js
socket = new WebSocket("ws://" + location.host + "/mahaplans/");
socket.onopen = function () {
var msg = {
status: "connecting"
};
socket.send(JSON.stringify(msg))
}
socket.onmessage = function (e) {
let status=JSON.parse(e.data)
if (status["status"]=="connected") {
var imageData={
#someddata
}
socket.send(JSON.stringify(imageData))
}
if (status["status"]=="sending") {
console.log(status["polygon"])
}
}
socket.onclose = function (event) {
console.log("bye bye")
}
if (socket.readyState == WebSocket.OPEN) socket.onopen();

Save() method thread safe or not in django

Is django's save method thread safe or not. Meaning that if i have multiple threads then will the save() method interfere with the data sent to each of the save() method ? Have faced this problem while running the save() method on multiple threads. I noticed that some of the fields values are interchanged meaning that the field value of one thread's save method has gone to the field value of the other thread. Is there a way to tackle with this situation?
from project.views import start_new_thread
from django.db import connection
#start_new_thread
def site(site,loop):
try:
from bs4 import BeautifulSoup
from django.db.models import Max
import re
import pytz
from datetime import datetime
from .sentiment_analysis import calculate_sentiment
import aiohttp
import asyncio
import async_timeout
from project.models import thread,post
import dateparser
href=[]
link=set()
tthread=[]
author={}
def convert_si_to_number(x):
total_stars = 0
if 'K' in x:
if len(x) > 1:
total_stars = float(x.replace('K', '')) * 1000 # convert k to a thousand
elif 'M' in x:
if len(x) > 1:
total_stars = float(x.replace('M', '')) * 1000000 # convert M to a million
elif 'B' in x:
total_stars = float(x.replace('B', '')) * 1000000000 # convert B to a Billion
else:
total_stars = int(x) # Less than 1000
return int(total_stars)
async def fetch(session, url):
async with async_timeout.timeout(30):
async with session.get(url) as response:
return await response.text()
async def forum(response,lockhref,lockthread):
soup = BeautifulSoup(response,'html5lib')
table = soup.findAll('a',href=re.compile("forums/"))
for row in table:
url ='site.com'+row['href']
async with lockhref:
if url not in link:
href.append(url)
link.add(url)
Th = soup.findAll('div',{'class':re.compile('structItem structItem--thread')})
for t in Th:
json_data={}
divs=t.findAll("div")
url="site.com"+(divs[2].div.find('a',href=re.compile('threads/')))['href']
json_data["id"]=url
dl=divs[5].findAll("dl")
json_data["views"]=convert_si_to_number(dl[1].dd.text)
f=thread.objects.filter(id=url)
async with lockthread:
if url not in link:
link.add(url)
if not len(f):
tthread.append(url)
else:
try:
if f[0].posts<convert_si_to_number(dl[0].dd.text)+1:
tthread.append(url)
except:
if f[0].posts<1:
tthread.append(url)
json_data["thread_title"]=divs[2].div.a.text
json_data["site"]="site.com"
json_data["posts"]=0
json_data["timestamp_ms"]=None
json_data["author"]=None
json_data["date_created"]=None
if not len(f):
t=thread(id=json_data["id"],thread_title=json_data["thread_title"],posts=json_data["posts"] ,views=json_data["views"],site=json_data["site"],timestamp_ms=json_data["timestamp_ms"],
author=json_data["author"],date_created=json_data["date_created"])
t.save()
elif f[0].views<json_data["views"]:
thread.objects.filter(id=json_data["id"]).update(views=json_data["views"])
async def showthread(url,j,lock):
async with aiohttp.ClientSession() as session:
try:
response = await fetch(session, url)
await threa(response,lock,url)
except (aiohttp.ClientConnectionError,aiohttp.ClientConnectorError):
print("Going to sleep for 5min")
await asyncio.sleep(300)
await showthread(url,j,lock)
except asyncio.TimeoutError :
print("Timeout Retrying")
await showthread(url,j,lock)
except Exception as e:
if j<2:
j+=1
print("error "+url+" "+str(e))
await showthread(url,j,lock)
async def threa(response,lock,url):
soup = BeautifulSoup(response, 'html5lib')
table = soup.findAll('a',href=re.compile(url+"page-\d+"))
for row in table:
async with lockthread:
if "site.com"+row["href"] not in link:
tthread.append("site.com"+row["href"])
link.add("site.com"+row["href"])
table = soup.findAll('div',{'class':'message-inner'})
match=re.finditer("page",url)
index=-1
for m in match:
index=m.start()
if index==-1:
id=url
else:
id=url[:index]
count=0
for t in table:
count=count+1
json_data={}
h4=t.find("h4",{'class':'message-name'})
try:
json_data["screen_name"]=h4.text
except:
json_data["screen_name"]="None"
div=t.find('div',{'class':'message-attribution-main'})
try:
json_data["created_at"]=dateparser.parse(' '.join(div.text.split()))
json_data["created_at"]=pytz.utc.localize(json_data["created_at"])
except Exception as e:
print(str(e))
json_data['created_at']=datetime(1970, 1, 1, 1, 1, 1, 0,pytz.UTC)
json_data['timestamp_ms']= datetime.timestamp(json_data['created_at'])
div=t.find('div',{'class':'bbWrapper'})
try:
full_text=''.join((div.text).split())
except:
full_text=''
text,sentiment=calculate_sentiment('ar',full_text)
json_data['sentiment_analysis']=sentiment
json_data["text"]=full_text
json_data["cleaned_text"]=text.split()
json_data["hashtags"]=''
json_data["id"]=id
try:
ul=t.find('ul',{'class':re.compile('message-attribution-opposite')})
li=ul.find('a',{'class':'qimahostma'})
no=int((li.text).replace("#",''))
except:
f=post.objects.filter(link=id)
if not len(f):
no=1
else:
max=f.aggregate(Max('no'))
no=max['no__max']+1
if int(no)==1:
json_data["quoted_screen_name"]=''
json_data["is_quote"]=False
author[url]=json_data["screen_name"]
thread_existing,created=thread.objects.get_or_create(id=json_data["id"])
if created:
thread_existing.date_created=json_data["created_at"]
thread_existing.timestamp=json_data["timestamp_ms"]
thread_existing.author=json_data["screen_name"]
thread_existing.thread_title=(soup.find('h1',{'class':'p-title-value'})).text
thread_existing.posts=0
thread_existing.views=-1
thread_existing.site="site.com"
thread_existing.save()
else:
thread_existing.thread_title=thread_existing.thread_title
thread_existing.posts=thread_existing.posts
thread_existing.views=thread_existing.views
thread_existing.site="site.com"
thread_existing.date_created=json_data["created_at"]
thread_existing.timestamp=json_data["timestamp_ms"]
thread_existing.author=json_data["screen_name"]
thread_existing.save()
else:
json_data["quoted_screen_name"]=author[url]
json_data["is_quote"]=True
json_data["no"]=int(no)
json_data["site"]="site.com"
try:
p=post(link=json_data["id"],no=json_data["no"],created_at=json_data["created_at"],hashtags=[],text=json_data["text"],cleaned_text=json_data["cleaned_text"]
,sentiment_analysis=json_data["sentiment_analysis"],quoted_screen_name=json_data["quoted_screen_name"],is_quote=json_data["is_quote"],site=json_data["site"],
timestamp_ms=json_data["timestamp_ms"],screen_name=json_data["screen_name"])
p.save()
except Exception as e:
print(e)
if count>0:
t=thread.objects.get(id=id)
t.posts=t.posts+count
t.save()
async def scrapping(url,j,lockhref,lockthread):
async with aiohttp.ClientSession() as session:
try:
response = await fetch(session, url)
await forum(response,lockhref,lockthread)
except (aiohttp.ClientConnectionError,aiohttp.ClientConnectorError):
print("Going to sleep for 5min")
await asyncio.sleep(300)
await scrapping(url,j,lockhref,lockthread)
except asyncio.TimeoutError :
print("Timeout Retrying")
await scrapping(url,j,lockhref,lockthread)
except Exception as e:
if j<2:
j+=1
print("error "+url+" "+str(e))
await scrapping(url,j,lockhref,lockthread)
href.append("site.com/index.php")
link.add("site.com/index.php")
asyncio.set_event_loop(loop)
lockhref = asyncio.Lock()
lockthread=asyncio.Lock()
no_of_concurrent_connections=50
i=0
while i<len(href):
if i+no_of_concurrent_connections<len(href):
tasks=[loop.create_task(scrapping(href[j],0,lockhref,lockthread)) for j in range(i,i+no_of_concurrent_connections)]
i+=no_of_concurrent_connections
else:
tasks=[loop.create_task(scrapping(href[j],0,lockhref,lockthread)) for j in range(i,len(href))]
i=len(href)
loop.run_until_complete(asyncio.gather(*tasks))
i=0
while i<len(tthread):
if i+no_of_concurrent_connections<len(tthread):
tasks=[loop.create_task(showthread(tthread[j],0,lockthread)) for j in range(i,i+no_of_concurrent_connections)]
i+=no_of_concurrent_connections
else:
tasks=[loop.create_task(showthread(tthread[j],0,lockthread)) for j in range(i,len(tthread))]
i=len(tthread)
loop.run_until_complete(asyncio.gather(*tasks))
finally:
print('ended')
connection.close()
These threads are created using a decorator
def start_new_thread(function):
def decorator(*args, **kwargs):
name=str(args[0])
t = Thread(name=name,target = function, args=args, kwargs=kwargs,daemon=True)
list[name]=t
t.start()
return decorator
Fixed the problem by closing the connection whenever i created a new process or a thread and then on the new process django automatically created a new connection whenever it is needed

Play2 testing controller methods using Action composition

I want to test a controller action using Action composition.
Here's an example of the composed action and its test code.
The Secured trait:
trait Secured {
def username(request: RequestHeader) = request.session.get(Security.username)
def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Auth.login)
def withAuth(f: => String => Request[AnyContent] => Result) = {
Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
}
The controller:
MyController extends Contrller with Secured {
def simple = Action { Ok("ok") }
def simpleWithauth = withAuth { implicit username => implicit request=> Ok("ok") }
}
The test code:
// This work fine
val result1 = controller.simple()(FakeRequest())
// This wont compile
val result2 = controller.simpleWithAuth()(FakeRequest())
The latter would require a Request[Action[AnyContent], AnyContent]
but FakeRequest returns a Request[AnyContent]
Any pointers on how to create a fake request of the appropriate type?
This is what I had to do to test secured action
def wrappedActionResult[A](wrapped: Action[(Action[A], A)], request: Request[A]): Result = wrapped.parser(request).run.await.get match {
case Left(errorResult) => errorResult
case Right((innerAction, _)) => innerAction(request)
}
and the test
running(app) {
val result = wrappedActionResult(FakeController().securedAction, invalidRequest)
status(result) must_== UNAUTHORIZED
contentAsString(result) must_== "must be authenticated"
}
That doesn't work with Play 2.1 though, types have been changed...
UPDATE:
in Play 2.1 it's even easier
I've added some sugar
implicit class ActionExecutor(action: EssentialAction) {
def process[A](request: Request[A]): Result = concurrent.Await.result(action(request).run, Duration(1, "sec"))
}
and the test now looks like this
running(app) {
val result = FakeController().securedAction process invalidRequest
status(result) must_== UNAUTHORIZED
contentAsString(result) must_== "must be authenticated"
}
UPDATE: here is a related blog post i wrote sometime ago
http://www.daodecode.com/blog/2013/03/08/testing-security-dot-authenticated-in-play-2-dot-0-and-2-dot-1/
Have you tried using the routeAndCall approach?
val Some(result) = routeAndCall(FakeRequest(POST, "/someRoute"))
You can add whatever parameters you need in your request with the asFormUrlEncodedBody method and/or adding things to the session with the withSession method.

Groovy-grails Mocking issue. Unable to Mock

I have a service class method in my grails porject which uses a helper class to fetch the response as xml. The xml is then send out as the response of the service class method.
ServiceClass:-
class ItemService{
def getItem(Number) {
def HelperClass helper = new HelperClass()
def responseXml = helper.getMessage(Number)
return responseXml
}
}
I writing a test case for this method. In my test case, i wish to mock
def responseXml = helper.getMessage(Number)
The test case that i have written so far is:
class ItemServiceTest extends GroovyTestCase {
public final void testFindItem(){
def service = new ItemService()
def xml = "<Item><Number>123</Number></Item>"
def mockJobServiceFactory = new MockFor(HelperClass)
mockJobServiceFactory.demand.getMessage{ def str ->
return xml
}
service.getItem().HelperClass = mockJobServiceFactory.proxyInstance()
def item = service.getItem()("123")
assertNotNull(item)
}
but still, the mock does not return the xml that I speicified in the test case.
Any problems that you see in the above approach?...Advance Thanks
When you mock objects with MockFor, you need to surround the code that uses the mock in a use closure. Try this:
def service = new ItemService()
def xml = "<Item><Number>123</Number></Item>"
def mockJobServiceFactory = new MockFor(HelperClass)
mockJobServiceFactory.demand.getMessage{ def str ->
return xml
}
mockJobServiceFactory.use {
def item = service.getItem()("123")
assertNotNull(item)
}