How mock a method with parameters and return an iterable in python - python-3.x

I need to test this function with a unit test:
def nlp_extraction(texts, nlp=None):
extr = []
for doc in nlp.pipe([texts]):
extr.append(list([ent.label_, ent.text]) for ent in doc.ents)
extracao = [list(extr[i]) for i in range(len(extr))]
extracao = list(chain.from_iterable(extracao))
extracao = " ".join([item[1] for item in extracao])
return [texts, extracao]
I wrote, inicialy, this test and worked:
def test_nlp_extraction_entrada_correta():
nlp = loadModel('ner_extract_ingredients')
result_reference = ['xilitol', 'xilitol']
texts = 'xilitol'
result = nlp_extraction(texts, nlp)
assert result == result_reference
But in this test I need to load the model. As this is an unit test, I would like to mock the responses, thus load an external model can be disable. I am trying something like this (and a combination of the lines commented in the code):
def test_nlp_extraction_entrada_correta():
texts = 'xilitol'
doc = Mock(name="DOC")
ents = Mock(name="ENTS", label_='xilitol', text="xilitol")
doc.ents = [ents]
from nextmock import Mock
nlp = Mock()
nlp_mock = Mock()
nlp.with_args([texts]).returns([doc])
nlp_mock.pipe = nlp([texts])
# nlp_mock.pipe.with_args([texts]).returns(doc)
# nlp_mock.pipe = [Mock(return_value=doc)]
result = nlp_extraction(texts, nlp=nlp_mock)
assert result == result_reference
But an error always raise, saying that nlp.pipe([texts]) mock object is not iterable. So, I need to mock this part nlp.pipe([texts]) and return the doc object. How I can do this? Something I am missing in the proccess, can someone help me.

As Cpt.Hook said in comments, the solution was achieved using nlp.pipe.return_value = [doc].

Related

PyTest how to properly mock imported ContextManager class and its function?

This is my sample code:
from path.lib import DBInterface
class MyClass:
def __init__(self):
self.something = "something"
def _my_method(self, some_key, new_setup):
with DBInterface(self.something) as ic:
current_setup = ic.get(some_key)
if current_setup != new_setup:
with DBInterface(self.something) as ic:
ic.set(new_setup)
def public_method(self, some_key, new_setup):
return self._my_method(some_key, new_setup)
(my actual code is bit more complex, but i cant put it here on public :)
Now, what I want to do is, I want to completely mock the imported class DBInterface, because I do not want my unittests to do anything in DB.
BUT I also need the ic.get(some_key) to return some value, or to be more precise, I need to set the value it returns, because thats the point of my unittests, to test if the method behave properly according to value returned from DB.
This is how far I got:
class TestMyClass:
def test_extractor_register(self, mocker):
fake_db = mocker.patch.object('my_path.my_lib.DBInterface')
fake_db.get.return_value = None
# spy_obj = mocker.spy(MyClass, "_my_method")
test_class = MyClass()
# Test new registration in _extractor_register
result = test_class.public_method(Tconf.test_key, Tconf.test_key_setup)
fake_db.assert_has_calls([call().__enter__().get(Tconf.test_key),
call().__enter__().set(Tconf.test_key, Tconf.test_key_setup)])
# spy_obj.assert_called_with(ANY, Tconf.test_key, Tconf.test_key_setup)
assert result.result_status.status_code == Tconf.status_ok.status_code
assert result.result_data == MyMethodResult.new_reg
But i am unable to set return value for call().__enter__().get(Tconf.test_key).
I have been trying many approaches:
fake_db.get.return_value = None
fake_db.__enter__().get.return_value = None
fake_db.__enter__.get = Mock(return_value=None)
mocker.patch.object(MyClass.DBInterface, "get").return_value = None
None of that is actually working and I am running out of options I can think about.
Without having more code or errors that are being produced, it's tough to provide a conclusive answer.
However, if you truly only need to specify a return value for set() I would recommend using MagicMock by virtue of patch --
from unittest.mock import patch
#patch("<MyClassFile>.DBInterface", autospec=True)
def test_extractor_register(mock_db):
mock_db.set.return_value = "some key"
# Rest of test code

How do I test for str equality using factory_boy faker method?

I have two factory classes, the other is linked to the one through foreign key relationships, and was kinda hoping to achieve some similarities with the attributes. To start with, the model looks something like this:
class Track(models.Model):
response = models.ForeignKey('Response')
def __str__(self):
return str(self.response)
class Response(models.Model):
title = models.CharField(max_length=640)
def __str__(self):
return self.title
I should be able to access these classes as I have done below
r = Response(title='foo')
r.save()
t = Track(response=r)
t.save()
# with this I wanted to test that str(t) == t.response
The factory classes look like this:
class ResponseFactory(factory.django.DjangoModelFactory):
class Meta:
model = Response
title = factory.Faker('text')
class TrackFactory(factory.django.DjangoModelFactory):
class Meta:
model = Track
response = factory.SubFactory(ResponseFactory)
Below is how I have accessed these factory classes to test for str equality
track = TrackFactory() # generates random string e.g `foo`
a = str(track) # == foo
b = track.response # == foo
# however I get an assertion error with the statement below
assert a == b
Could you point out where I've gone wrong, thank you.

Execute python method from a string

I have a string that has the method name and value in it. Currently, I'm using the following implementation which works but doesn't seem elegant. Is there a better way to implement this?
class ObjectResolver:
def methodResolver(self, value):
"""Some logic here"""
print(value)
objectResolver = ObjectResolver()
channel = 'methodResolver(helloWorld)'
findValue = channel.strip().find('(')
objectMethod = channel.strip()[:findValue]
attribute = channel.strip()[findValue:][1:-1]
channelResolver = getattr(objectResolver, objectMethod)(attribute)
Output:
helloWorld
You can use eval() or exec()
class ObjectResolver:
def methodResolver(self, value):
"""Some logic here"""
print(value)
objectResolver = ObjectResolver()
// Something like this...
channel = eval('methodResolver')(helloWorld)
// OR
exec('channel = "methodResolver(helloWorld)"')
findValue = channel.strip().find('(')
objectMethod = channel.strip()[:findValue]
attribute = channel.strip()[findValue:][1:-1]
channelResolver = getattr(objectResolver, objectMethod)(attribute)
Learn more about eval and exec
The best method I found is to use eval here and specifically to my question above, the implementation is as follows:
class ObjectResolver:
def methodResolver(self, value):
"""Some logic here"""
print(value)
objectResolver = ObjectResolver()
channel = "methodResolver('helloWorld')"
handlers = dict(methodResolver=objectResolver.methodResolver)
eval(channel, handlers)

Mocking a resource from outerscope of a function in python

I have a function that uses a dictionary, constructed out of the function, and do something. The function is like this:
TRANSLATION_TABLE = {#something}
def get_translate(tokens_and_tags):
results = []
for token, tag in tokens_and_tags:
results.append((TRANSLATION_TABLE.get(token, token), tag))
return results
Now I want to write test for it, but, I could not find how to mock the "TRANSLATION_TABLE" dictionary properly.
What is the correct way to test this function and mocking the dictionary?
You want to use dependency injection
def get_translate(tokens_and_tags, translation_table=None)
translation_table = translation_table or TRANSLATION_TABLE
Now you can inject a fake in your test.
def test_get_translate(...):
...
expect = ...
actual = get_translate(fake_tokens_and_tags, {...})
assert actual == expect.

Sorting arrays in Groovy

I'm trying to compare two arrays in groovy. My attempts so far have yielded a mixed response and therefore I'm turning to the collective for advice.
In the following code I'm taking 2 REST responses, parsing them and placing everything under the Invoice node into an array. I then further qualify my array so I have a list of InvoiceIDs and then try to compare the results of the two responses to ensure they are the same.
When I compare the array of InvoiceIDs (Guids) they match - this is not what I expect as the invoice order is currently different between my my 2 response sources.
When I sort the arrays of Invoices IDs the results differ.
I'm suspecting my code is faulty, but have spent an hour rattling through it, to no avail.
Any advice on sorting arrays in groovy or on the code below would be most appreciated:
gu = new com.eviware.soapui.support.GroovyUtils( context )
def xmlSlurper = new groovy.util.XmlSlurper()
// Setting up the response parameters
def responseSTAGE = xmlSlurper.parseText(context.expand('${GET Invoices - STAGE#Response}'));
def responseSTAGE2 = xmlSlurper.parseText(context.expand('${GET Invoices - STAGE2#Response}'));
responseInvoicesSTAGE = responseSTAGE.Invoices
responseInvoicesSTAGE2 = responseSTAGE2.Invoices
def arrayOfInvoicesSTAGE = []
def arrayOfInvoicesSTAGE2 = []
def counter = 0
for (invoice in responseInvoicesSTAGE.Invoice) {
arrayOfInvoicesSTAGE[counter] = responseInvoicesSTAGE.Invoice[counter].InvoiceID
//log.info counter+" STAGE"+arrayOfInvoicesSTAGE[counter]
arrayOfInvoicesSTAGE2[counter] = responseInvoicesSTAGE2.Invoice[counter].InvoiceID
//log.info counter+" STAGE2"+arrayOfInvoicesSTAGE2[counter]
counter++
}
log.info arrayOfInvoicesSTAGE
log.info arrayOfInvoicesSTAGE2
def sortedSTAGE = arrayOfInvoicesSTAGE.sort()
def sortedSTAGE2 = arrayOfInvoicesSTAGE2.sort()
log.info sortedSTAGE
As an aside, can't you replace:
def arrayOfInvoicesSTAGE = []
def arrayOfInvoicesSTAGE2 = []
def counter = 0
for (invoice in responseInvoicesSTAGE.Invoice) {
arrayOfInvoicesSTAGE[counter] = responseInvoicesSTAGE.Invoice[counter].InvoiceID
//log.info counter+" STAGE"+arrayOfInvoicesSTAGE[counter]
arrayOfInvoicesSTAGE2[counter] = responseInvoicesSTAGE2.Invoice[counter].InvoiceID
//log.info counter+" STAGE2"+arrayOfInvoicesSTAGE2[counter]
counter++
}
with
def arrayOfInvoicesSTAGE = responseInvoicesSTAGE.Invoice*.InvoiceID
def arrayOfInvoicesSTAGE2 = responseInvoicesSTAGE2.Invoice*.InvoiceID
Two arrays are considered equal in Groovy if they have they have the same number of elements and each element in the same position are equal. You can verify this by running the following code in the Groovy console
Integer[] foo = [1,2,3,4]
Integer[] bar = [4,3,2,1]
assert foo != bar
bar.sort()
assert foo == bar

Resources