Mockk verify fails when checking called and wasNot called - kotlin

I am trying to verify that a function was not called using the following:
verify {
managementService.deleteUser(any()) wasNot Called
}
That verification fails with the message:
Verification failed: call 1 of 1:
ManagementService(#11).deleteUser(any())) was not called.
If I invert the verification to this:
verify {
managementService.deleteUser(any())
}
I still receive the same failure message.
There are other functions on ManagementService that pass wasNot Called just fine.
Why would my verification failing for wasNot Called, while the error message says the failure is because it was not called? And why would inverting the check produce the same error?

wasNot Called is not used to verify that a specific function call has not been made, but that an entire mock was never called, like this:
verify {
managementService wasNot Called
}
If you want to verify that deleteUser was not called with any argument, you can verify that the call happened exactly zero times:
verify(exactly = 0) {
managementService.deleteUser(any())
}

Related

How to test subscribe call of Observable using Mockk?

I have a function in my ViewModel in which I subscribe to some updates, I want to write a test that will check that after the subscribe is triggered, the specific function is called from the subscribe.
Here is how the function looks:
fun subscribeToTablesUpdates() {
dataManager.getTablesList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { tablesList ->
updateTablesState(tablesList)
}
}
And this is the test that I wrote:
#Test
fun subscribeToTablesListTest() {
val mockedTablesList = mockk<List<Table>()
every {
viewModel.dataManager.getTablesList()
} returns Observable.just(mockedTablesList)
viewModel.subscribeToTablesUpdates()
verify {
viewModel.updateTablesState(mockedTablesList)
}
}
The issue is that I receive assertion exception without any another info and I don't know how to fix that.
Edit 1: subscribeToTableUpdates() is calling from the init block of ViewModel.
So basically the test itself was done right, but there were linking issue. Since the function of the VM was called from the init block the subscription happened only once, and that created a situation when at the time when I mocked the data service, the observer was already subscribed to the other service. Since the init block is called only once, there is no way to change the implementation of the data service to that observer.
After all this investigation the one thing which I successfully forgot came to my mind again: extract every external dependencies to constructors, so further you could substitute it for the test without any problems like this.

What is the analogue of Mockito.verifyZeroInteractions(obj) in the Mockk library?

I want to switch to Mockk, but i cant find analogue of this method in Mockk
It doesn't work
verify (exactly = 0) { obj }
The way you are trying it, is missing the method or variable
verify (exactly = 0) { obj.something }
Using the exactly zero approach would require
confirmVerified(obj)
To be sure nothing else was called.
The exact equivalent would be:
verify { obj wasNot Called }

MockK verify return value

I need to verify that a function is being called. When I run debug, I can see it being called but I get this error from mockk:
Verification failed: call 1 of 1: Object(#2).f(any(), any())) was not called.
My verify statemen is as follows:
verify(exactly = 1) { object.f(any(), any()) }
And I create the spy object as follows:
object = spyk(object)
The signature of the function f is:
f(any(), any()) : String
Can someone please point me in the right direction, how do I use verify for the function f. I suspect that because the function f returns a string, verify cannot match it's signature.
In any case, please let me know if you have an idea of why verify doesn't work in this case.
Thanks

Why jest expects an anonymous function to catch an error?

I have not comprehended what's the reason behind the fact that expects a curried function when I want to test the output of the error message. If it was going to be a return value a direct call to the function leads to the value to be tested correctly in .toBe
function calculateMedian({numbers}) {
if (Array.isArray(numbers) && numbers.length === 0) {
throw new Error('Cannot calcuate median without any numbers');
}
}
However, if i were to test the following snipped without the anonymous function the test will simply fail. What is the reason behind it?
Passing Test
it('should throw an error when given an empty array', () => {
expect(() =>
calculateMedian({
numbers: [],
}),
).toThrow('Cannot calcuate median without any numbers');
});
Failing Test
it('should throw an error when given an empty array', () => {
expect(calculateMedian({numbers: []})
).toThrow('Cannot calcuate median without any numbers');
});
expect and toThrow are just function calls. So, for the assertion on exception to work, the thing you pass as expect argument needs to allow for execution controlled by the testing framework.
The flow is similar to:
expect() saves the lambda as variable
toThrow() executes the saved variable in a try/catch block and tests the caught exception.
The way you would do it without the toThrow method would be similar to:
try {
calculateMedian({numbers: []};
fail();
} catch (err) {
expect(err.message).toBe('Cannot calcuate median without any numbers')
}
If, instead of passing a lambda/function you simply invoke the function, the error will be thrown before program control gets to the toThrow method. The test will fail because of the thrown error.

When does a strongloop promise execute the database call?

I was refactoring someone elses code.
let promiseObj = Application.models.Widget.findById(connection.childId)
if (connection.child != 'Widget') {
typeES = "media"
promiseObj = Application.models.Media.findById(connection.childId)
}
promiseObj.then((obj) => {
let ownerId = obj.ownerId
let promiseUser = Application.models.MyUser.findById(ownerId)
})
The question is, does the server get called when
"let promiseObj = Application.models.Widget.findById(connection.childId)" is declared.
Or does the server get called when the .then is declared as the promise have a way to be fulfilled.
This is loopback with ES6.
Thanks guys/girls :D
Does the server get called when let promiseObj = Application.models.Widget.findById(connection.childId) is declared.
Yes, the server request is made as soon as the findById method is called.
Or does the server get called when the .then is declared as the promise have a way to be fulfilled.
then is just a method that is called, there is no declaration here. And it doesn't "give the promise a way to be fulfilled" - the promise will always resolve when the request finishes (fulfill in case of success and reject in case of an error), regardless whether there are any callbacks or not.
If you install a callback via then, it will be called when the promise is fulfilled.
So yes, I'm pretty certain that you should refactor this code:
let promiseObj;
if (connection.child != 'Widget') {
promiseObj = Application.models.Widget.findById(connection.childId);
} else {
typeES = "media"
promiseObj = Application.models.Media.findById(connection.childId)
}
let promiseUser = promiseObj.then((obj) => {
return Application.models.MyUser.findById(obj.ownerId);
});
As Erazihel is explaining, the declaration does not fire the resolve, it is called when you call .then()
I made a simple example in order to visualize the effect, there you will check that the time of the resolve matches the time where you call .then(), not on declaration.
p1.then(
// Then calls the resolve so the execution time 'resolve' matches .then
function(val) {
var timeMeAgain = new Date().toLocaleString();
log.insertAdjacentHTML('beforeend', val.thisPromiseCount +
') Promise done, then is called here (<small>Async call finished, .then called at: '+timeMeAgain+', promise executed at": '+val.timeCalledAt+' </small>)<br/>');
})
Check the example code here
*Code is based in the MDN example. Check documentation here
EDIT
About the resolve method, as the MDN documentation explains:
The method returns a Promise object that is resolved with the given value.
If the value is a thenable (i.e. has a "then" method), the returned
promise will "follow" that thenable, adopting its eventual state;
otherwise the returned promise will be fulfilled with the value.
Meaning that the response object will be returned when the Database or endpoint returns the information, not on declaration of the promise.