I am calling Future like this:
//main_bloc.dart
...
getData() {
print("getting data");
repository.getDataFromServer().then((result) {
_handleResult(result);
}).catchError((e) {
_handleError(e);
});
}
In runtime, when there is exception from the repository, it will be catched in the catchError and forward properly.
However, when i do unit testing to that part of code like this:
//prepare
when(mockRepository.getDataFromServer()).thenThrow(PlatformException(code: "400", message: "Error", details: ""));
//act
bloc.getData();
await untilCalled(mockRepository.getDataFromServer());
//assert
verify(mockRepository.getDataFromServer());
The catchError method not called and the test is failed due to unHandled exception.
What i am doing wrong?
Your code expects to catch an error from a returned Future. Your mock throws an exception immediately (synchronously) when it is invoked; it never returns a Future.
I think that you instead would need to do:
when(repository.getDataFromServer()).thenAnswer((_) => Future.error(
PlatformException(code: "400", message: "Error", details: "")));
A simpler (and more robust) change would be to use try-catch in your code instead of Future.catchError:
Future<void> getData() async {
print("getting data");
try {
_handleResult(await repository.getDataFromServer());
} catch (e) {
_handleError(e);
}
}
Related
I tried many references available regarding the same but nothing worked.
I have a method in Kotlin which can throws Checked and unchecked exceptions both(depend on which block in throwing the exception)
fun deleteItem(tokens: List<String>, userId: Long) {
val records = storeRegistry.readItemsByTokens(tokens)
val missingTokens = tokens.toSet() - records.map { it.token }.toSet()
if (missingTokens.isNotEmpty()) {
throw EntityNotFoundException( // checked exception
"Item with tokens=$missingTokens does not exist."
)
}
transactionManager.executeInTransaction {
tokens.forEach {
val success = storeRegistry.deleteItemByToken(it, userId)
if (!success) {
throw InternalException.badRequest( // unchecked exception
"Item delete failed: item token=$it"
)
}
}
}
}
This method is called from some other's class method which is in test. and Unit test look like this
#Test
fun deleteItemShouldThrowIfEntityNotFound() {
whenever(ItemManager.deleteItemsByTokens(any(), any()))
.thenAnswer { throw EntityNotFoundException() }
val deleteRequest = ItemsDeleteRequest.builder()
.ItemsDeleteParams(
listOf(
ItemDeleteParams.createToken("token1"),
ItemDeleteParams.createToken("token2"),
)
).build()
// act
try {
getAfterburner().ignite(
buildServiceRequest(deleteRequest),
DEFAULT_TEST_TIMEOUT
).join()
} catch (e: Exception) {
assert(e.cause is EntityNotFoundException)
}
verify(ItemManager, times(1))
.deleteItemsByTokens(listOf("token1", "token2"), 123456L)
}
When I run above test, I got this error
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: com.abc.xtz.api.EntityNotFoundException
Mockito won't throw a checked exception for a function that doesn't have the checked exception as part of its signature. To be able to do this, you need to add the checked exception to the function signature using #Throws:
#Throws(EntityNotFoundException::class)
fun deleteItem(tokens: List<String>, userId: Long) {
//...
The code I'm trying to test:
const utils = require('../utils/utils');
let imageBuffer;
try {
imageBuffer = await utils.retrieveImageFromURI(params)
console.log(imageBuffer) // comes back as undefined when I mock the utils.retreieveImageFromURI
if (!imageBuffer || imageBuffer.length < 1024) {
throw new Error(`Retrieve from uri (${params.camera.ingest.uri}) was less than 1kb in size - indicating an error`)
}
console.log(`${params.camera.camId} - Successful Ingestion from URI`);
} catch (err) {
reject({ 'Task': `Attempting to pull image from camera (${params.camera.camId}) at ${params.camera.ingest.uri}`, 'Error': err.message, 'Stack': err.stack })
return;
}
Specifically, I'm trying to mock the utils.retrieveImageFromURI function - which has API calls and other things in it.
When I try to mock the function using spyOn I am trying it like so:
describe("FUNCTION: ingestAndSave", () => {
let fakeImageBuffer = Array(1200).fill('a').join('b'); // just get a long string
console.log(fakeImageBuffer.length) //2399
let retrieveImageFromURISpy
beforeAll(() => {
retrieveImageFromURISpy = jest.spyOn(utils, 'retrieveImageFromURI').mockReturnValue(fakeImageBuffer)
})
test("Will call retrieveImageFromURI", async () => {
await ingest.ingestAndSave({camera:TEST_CONSTANTS.validCameraObject, sourceQueueURL:"httpexamplecom", receiptHandle: "1234abcd"})
expect(retrieveImageFromURISpy).toHaveBeenCalledTimes(1)
})
afterEach(() => {
jest.resetAllMocks()
})
afterAll(() => {
jest.restoreAllMocks()
})
})
When I do this, I get a console log that imageBuffer (which is supposed to be the return of the mocked function) is undefined and that, in turn, triggers the thrown Error that "Retrieve from uri ...." ... which causes my test to fail. I know I could wrap the test call in a try/catch but the very next test will be a "does not throw error" test... so this needs to be solved.
It's not clear to me why the mockReturnValue isn't getting returned.
Other steps:
I've gone to the REAL retrieveImageFromURI function and added a console log - it is not running.
I've changed mockReturnValue to mockImplementation like so:
retrieveImageFromURISpy = jest.spyOn(utils, 'retrieveImageFromURI').mockImplementation(() => {
console.log("Here")
return fakeImageBuffer
})
And it does NOT console log 'here'. I'm unsure why not.
I have also tried to return it as a resolved Promise, like so:
retrieveImageFromURISpy = jest.spyOn(utils, 'retrieveImageFromURI').mockImplementation(() => {
console.log("Here")
return Promise.resolve(fakeImageBuffer)
})
Note, this also doesn't console log.
I've also tried to return the promise directly with a mockReturnValue:
`retrieveImageFromURISpy = jest.spyOn(utils, 'retrieveImageFromURI').mockReturnValue(Promise.resolve(fakeImageBuffer)`)
I am unable to get the result of the assertion. Below mentioned are the example
//Code
pm.test(“Status code is 200”, function() {
pm.response.to.have.status(2001);
});
I wanted to get the result in variable so i can use this assertion value in other code(as mentioned in attached email).
For example: Save value of "Status code is 200 | AssertionError: expected response to have status code 2001 but got 401" in VARIABLE
See image
let error;
pm.test("Status code is 200", function () {
try {
pm.response.to.have.status(2001);
}
catch (err) {
error = err
pm.response.to.have.status(2001);
}
});
console.log(error)
just use try and catch, I am not sure why this is a use case. you can this to variable as
pm.environment.set("error",error)
Anybody can help me with this? I have this small code:
getUserDetailsApi().flatMap(){users in
return getScoreApi(users[0])
}.subscribe(
onCompleted: {
print("Done")
},
onError: {
// which of the two APIs get an error?
})
I call two APIs here, in the getUserDetailsApi I want to invoke an error when it failed to get the user details or something went wrong and skip the getScoreApi. Same on the getScoreApi if it fails to get the score of the user it will throw a different error.
is there a way I can throw the said errors on flatMap()?. Note that the two observable must be execute in sequence order and these errors has different message
You should throw the error in getUserDetailsApi() and getScoreApi().
Example:
func getUserDetailsApi() -> Observable<[User]> {
return Observable.create { observer in
// Your api call
// ...
// Probably you get the users array or an error.
if (error) {
observer.onError(YourError.UserDetailsError) // <- Your error
} else {
observer.onNext(users)
observer.onCompleted()
}
return Disposables.create {
// your dispose
}
}
}
And the same for getScoreApi(). Then, if one of them fails, the flatMap will fail.
getUserDetailsApi().flatMap(){users in
return getScoreApi(users[0])
}.subscribe(
onCompleted: {
print("Done")
},
onError: {
switch error{
case .userDetailsError:
// ...
case .otherError:
// ...
}
})
I have 2 simple methods that abstract reading and writing to localStorage:
_readLocalStorage: function(key) {
if (window.localStorage && window.localStorage.getItem(key)) {
return JSON.parse(window.localStorage.getItem(key));
} else {
throw new Error('Could not read from localStorage');
}
},
_writeLocalStorage: function(key, data) {
try {
window.localStorage.setItem(key, JSON.stringify(data));
} catch (e) {
throw new Error('Could not write to localStorage');
}
},
Obviously, stubbing window.localStorage.getItem/setItem is simple. But what about the case where localStorage is undefined?
I've tried caching/unhinging window.localStorage (the second assertion):
describe('#_readLocalStorage', function() {
it('should read from localStorage', function() {
// set up
var stub1 = sinon.stub(window.localStorage, 'getItem')
.returns('{"foo": "bar"}');
// run unit
var result = service._readLocalStorage('foo');
// verify expectations
expect(result)
.to.eql({foo: 'bar'});
// tear down
stub1.restore();
});
it('should throw an error if localStorage is undefined', function() {
// set up
var cachedLocalStorage = window.localStorage;
window.localStorage = undefined;
// run unit/verify expectations
expect(service._readLocalStorage('foo'))
.to.throw(new Error('Could not write to localStorage'));
// tear down
window.localStorage = cachedLocalStorage;
});
});
This does not work however. Mocha/Chai seem not to catch the thrown error.
I've looked around a bit but can't find any way to handle this.
Your expect should be
expect(service._readLocalStorage.bind(service, 'foo'))
.to.throw(new Error('Could not write to localStorage'));
The way you have it you code calls service._readLocalStorage('foo') before expect is called. So it raises an exception that expect cannot handle. What expect needs to be able to deal with exceptions is a function that expect itself will call. Using service._readLocalStorage.bind(service, 'foo') creates a new function that when called without arguments (as expect does) will be equivalent to calling service._readLocalStorage('foo').
There's another problem with your test: your cleanup code will never execute. The assertion libraries report problems by raising JavaScript exceptions. So any code that follows a failed exception won't run unless the exception is specially handled. You could do:
it('should throw an error if localStorage is undefined', function() {
// set up
var cachedLocalStorage = window.localStorage;
window.localStorage = undefined;
// run unit/verify expectations
try {
expect(...)...;
expect(...)...;
...
}
finally {
// tear down
window.localStorage = cachedLocalStorage;
}
});
For more complex cases, you should use before, beforeEach, after, afterEach for setup and teardown.