I'm trying to mock a SOAPProxy call, setting a return value, but it is refusing to work:
#patch('SOAPpy.SOAPProxy')
def test_check_cedible_mock(self, mock_soappy):
mock_soappy.getToken.return_value = ':)'
#calling the function...
In the function, it is used like this:
from SOAPpy import SOAPProxy
_server = SOAPProxy(url, ns)
tree = etree.fromstring(signed_seed)
ss = etree.tostring(tree, pretty_print=True, encoding='iso-8859-1')
resp = etree.fromstring(_server.getToken(ss).encode('utf-8'))
But _server.getToken(ss) is returning a MagickMock object.
How can I make it to work? Thanks.
Related
I have some tests for functions that use cache, for example:
Function:
#retry(stop=stop_after_attempt(3))
#cache.cached(timeout=60, key_prefix='resouce_group_list')
def get_azure_resource_groups():
data = []
resource_client = get_azure_resource_client()
for item in resource_client.resource_groups.list():
data.append(item)
return data
Test:
#patch("dev_maintenance.machines.get_azure_resource_client")
def test_get_azure_list_rg(get_azure_resource_client):
cache.clear()
data = []
with app.app_context():
ret = get_azure_resource_groups()
get_azure_resource_client.assert_called_once()
expected = get_azure_resource_client.return_value.resource_groups.list.return_value
assert len(get_azure_resource_client.return_value.method_calls) == 1
for item in expected:
data.append(item)
assert ret == data
cache.clear()
The above test works fine, it passes, no errors and the test is using cache.
But i got other tests, and the decorator here does not matter, it will give the same error if i change the decorator to #cache.cache:
Function:
#retry(stop=stop_after_attempt(3))
#cache.memoize(60)
def get_azure_machine_info(rg_name, machine_name, expand="instanceView"):
try:
compute_client = get_azure_compute_client()
return compute_client.virtual_machines.get(rg_name, machine_name, expand=expand)
except CloudError:
return None
Test:
#patch("dev_maintenance.machines.get_azure_compute_client")
def test_get_azure_machine_info (get_azure_compute_client):
cache.delete_memoized(get_azure_machine_info)
with app.app_context():
ret = get_azure_machine_info("rg1", "m1")
print(ret)
get_azure_compute_client.assert_called_once()
assert len(get_azure_compute_client.return_value.method_calls) == 1
assert (
ret == get_azure_compute_client.return_value.virtual_machines.get.return_value
)
get_azure_compute_client.return_value.virtual_machines.get.assert_called_once_with(
"rg1", "m1", expand="instanceView"
)
cache.delete_memoized(get_azure_machine_info)
Now here the test fails with the error on this line ret = get_azure_machine_info("rg1", "m1"):
value = None, from_value = PicklingError("Can't pickle <class 'unittest.mock.MagicMock'>: it's not the same object as unittest.mock.MagicMock")
> ???
E tenacity.RetryError: RetryError[<Future at 0x105c7c3d0 state=finished raised PicklingError>]
<string>:3: RetryError
I tried to mock the cache passing a patch decorator like:
#patch("dev_maintenance.machines.cache") or #patch("dev_maintenance.cache")
I tried to set the CACHE_TYPE to null in the test case, instantiating the cache object and passing the config:
cache = Cache()
cache.init_app(app, config={"CACHE_TYPE": "redis"})
but no success so far, any help?
This is a reference to an old answer, but I think that generally MagicMock objects aren't meant to be pickled: https://github.com/thadeusb/flask-cache/issues/52
That error message is different though, and this is more similar to what you are seeing:
Is there a way to make python pickle ignore "it's not the same object " errors
Maybe you could replace the domain prefix to the class like the answer above, but I am not sure it will overcome the other difficulties of pickling a MagicMock class:
`#patch("__main__.get_azure_compute_client")`
I'am writing the answer here for people that need to test functions that are cached with flask-caching and have the same error then me.
What i needed was to create an Object inside the test and make the mock_value = Object like this:
First i create a simple class:
class MachineInfo(object):
pass
Then in my test:
#patch("dev_maintenance.machines.get_azure_compute_client")
def test_get_azure_machine_info (get_azure_compute_client):
cache.clear()
expected_res = MachineInfo()
expected_res.id = "id"
expected_res.name = "machine1"
expected_res.location = "location"
expected_res.hardware_profile = "hardware"
expected_res.storage_profile = "storage"
expected_res.network_profile = "network_profile"
get_azure_compute_client.return_value.virtual_machines.get.return_value = expected_res
res = get_azure_machine_info("rg1", "m1")
assert res == expected_res
cache.clear()
Then i could assert function_call() == Object or function_call() == mock.return_value
This simulates what the actual azure returns, an object, so i just make the mock return the object that i created so i can simulate the function itself.
I have some code on the follwing form:
#Language("SQL")
val someSql = """
SELECT foo
FROM bar
WHERE foo = :foo
"""
return session.select(some, mapOf("foo" to foo)) {
MyObject(
foo = it.string("foo"),
)
}.firstOrNull()
which use the below from com.github.andrewoma.kwery.core. Note the lambda in the method signature:
fun <R> select(#Language("SQL") sql: String,
parameters: Map<String, Any?> = mapOf(),
options: StatementOptions = defaultOptions,
mapper: (Row) -> R): List<R>
I use mockitokotlin2.
I need to return an instance of MyObject when the session select method is called with a select query (containing "SELECT foo").
I was thinking I could pass a mock into the lambda as below (but then it wont match the method call I am trying to mock). The below code is an attempt. But it never matches in eq(function2):
val function2: (Row) -> Int = mock {
onGeneric { invoke(any()) }.thenReturn(MyObject(foo="test-foo"))
}
val session = mock<Session> {
on { select(sql = any(), parameters = any(), options = any(), mapper = eq(function2))}.thenReturn(listOf(MyObject(foo="test-foo")))
}
function2 in my case is not really a mapper, it is not eq to what I am trying to mock, it never matches and the mock is never called.
So what do I put in the mock of session, select instead of eq(function2) in the code above to get MyObject object returned?
I think you just need to specify they type that your mapper is expected to return when setting up the session mock - in your case looks to be Function1<Row, MyObject>
val session = mock<Session> {
on { select(sql = anyString(), parameters = anyMap(), options = any(), mapper = any<Function1<Row, MyObject>>())}.thenReturn(listOf(MyObject(foo="test-foo")))
}
I've following old method written in code, which is for accessing request object in service class such as:
def someServiceMethod() {
....
def webUtils = WebUtils.retrieveGrailsWebRequest()
def request = webUtils.getCurrentRequest()
MultipartHttpServletRequest mpr = (MultipartHttpServletRequest) request
CommonsMultipartFile file = (CommonsMultipartFile) mpr.getFile("file")
....
}
This is my unit test code for serivce class.
#TestFor(SomeService)
class SomeServiceSpec extends Specification {
void "test someServiceMethod"() {
given:
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest()
FileInputStream inFile = new FileInputStream("./test-data/Hiearchy-003.xlsx") //valid file path
def multipartFile = new GrailsMockMultipartFile('file', 'file.xls', 'multipart/form-data', inFile)
request.addFile(multipartFile)
GrailsWebRequest webRequest = new GrailsWebRequest(
request,
new MockHttpServletResponse(),
new MockServletContext()
)
request.setAttribute(GrailsApplicationAttributes.WEB_REQUEST,webRequest)
RequestContextHolder.setRequestAttributes(webRequest);
when:
def result = service.someServiceMethod()
then:
result != null
//some more assertions
//..
}
}
I'm stuck with following error.
| Failure: test someServiceMethod(SomeServiceSpec)
| org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'org.codehaus.groovy.grails.plugins.testing.GrailsMockMultipartFile#6ae8e5dd' with class 'org.codehaus.groovy.grails.plugins.testing.GrailsMockMultipartFile' to class 'org.springframework.web.multipart.commons.CommonsMultipartFile'
Anybody faced such issue before in grails unit test?
Instead of : GrailsMockMultipartFile,
use: org.springframework.mock.web.MockMultipartFile.
I just realised following line is just unnecessary if we use input stream direct it should not be problem hence solved my issue..
CommonsMultipartFile file = (CommonsMultipartFile) mpr.getFile("file")
I have this piece of code in a controller:
def update = {
Map model = [:]
model.foo = params.foo
model.bar = params.bar
def result = ""
MyObject obj = MyObject.findWhere(bar:bar, foo:foo)
MyObjectService.updateObj(model,obj)
result = true
render result as JSON
}
And this simple unit test:
def 'controller update'() {
given:
controller.params.foo = foo
controller.params.bar = bar
MyObject obj = new MyObject(bar:bar, foo:foo)
mockDomain(MyObject,[obj])
when:
controller.update()
then:
1 * MyObject.findWhere(bar:bar, foo:foo) >> obj
1 * MyObjectService.updateObj(model,obj)
and:
def model = JSON.parse(controller.response.contentAsString)
model == true
where:
foo = "0"
bar = "1"
}
Now this is failing by and it is telling me that, "not static method findWhere is applicable..." for those arguments. That "MyObject" is just an orm class, and when I run that application everything seems to be working fine, but the test is failing.
My logic is this:
I want to count how many times the findWhere and updateObj methods are call and I am also mocking their response. So findWhere will return the object I already mocked, and pass it on to the service.
Any ideas why this is failing ?
For mocking static methods you should use Spock's GroovyStub class which introduced in v0.7.
def retrieveEatenFood(String token, String addedDate) {
def consumer = Consumer.findByMobileToken(token)
if(consumer != null) {
def efList = []
def list = consumer.findAll("from EatenFood as ef where date(ef.dateAdded) = date(:da)",[da:sdf_long.parse(addedDate)])
list.each{
def eatenList = [:]
eatenList.put("foodType",it.food.name)
eatenList.put("sequenceNumber",it.sequenceNumber)
eatenList.put("eatenDate", it.eatenDate)
eatenList.put("DateAdded",it.dateAdded)
efList.add(eatenList);
}
return efList;
}
}
Trying to mock the above method, but the findAll keep generating an exception.
This issue it works! Now i need to write the test for it and i keep getting this exception. Can anyone help me please!
groovy.lang.MissingMethodException: No signature of method: carrotdev.Consumer.findAll() is applicable for argument types: (java.lang.String, java.util.LinkedHashMap) values: [from EatenFood as ef where date(ef.dateAdded) = date(:da), [da:Sun Feb 13 01:51:47 AST 2011]]
Possible solutions: findAll(groovy.lang.Closure), find(groovy.lang.Closure)
at carrotdev.ConsumerService.retrieveEatenFood(ConsumerService.groovy:146)
at carrotdev.ConsumerService$retrieveEatenFood.call(Unknown Source)
at carrotdev.ConsumerServiceTests.testEatenFoodRetrievedSucessfully(ConsumerServiceTests.groovy:359)
I would move the query to the Consumer domain class with a descriptive name, e.g.
static List<EatenFood> findAllEatenByDate(String date) {
consumer.findAll(
"from EatenFood as ef where date(ef.dateAdded) = date(:da)",
[da:sdf_long.parse(addedDate)])
}
Then the call is simply
def list = Consumer.findAllEatenByDate(addedDate)
and you can mock that easily with
def foods = [new EatenFood(...), new EatenFood(...), ...]
Consumer.metaClass.static.findAllEatenByDate = { String date - > foods }
Be sure to test the finder method in your Consumer integration test.