Flutter how to mock a call to rootBundle.loadString(...), then reset the mocked behavior? - flutter

In my flutter code, I have logic that does this:
final jsonString = await rootBundle.loadString('AssetManifest.json');
And I have tests that I want to return a fake AssetManifest.json when this line is reached.
To mock it, I do this in the test:
ServicesBinding.instance.defaultBinaryMessenger
.setMockMessageHandler('flutter/assets', (message) {
final Uint8List encoded =
utf8.encoder.convert('{"Foo.ttf":["Foo.ttf"]}');
return Future.value(encoded.buffer.asByteData());
});
The weird thing is, this works, but any tests that run after it hang (they all get stuck in the code when it reaches the await rootBundle.loadString('AssetManifest.json') line.
I've tried adding
ServicesBinding.instance.defaultBinaryMessenger
.setMockMessageHandler('flutter/assets', null);
But this doesn't seem to properly "clean up" the mocked behavior. In fact, if I run the above line in my setUp, the first test to run hangs.
So am I mocking the behavior wrong? Or am I not cleaning it up properly?

I ran into the same issue, and believe it's due to caching by the bundle. This will cause the above test to fail, because the message never gets sent. When calling loadString, you can specify whether to cache the result. E.g. loadString('AssetManifest.json', false).
Note that if you use loadStructuredData, implementations can cache the result and you can't tell it not to.

Related

Is it possible to write all console output to a variable in Dart / Flutter

I have deployed my flutter app and one user says that a certain part is not working. Therefore, I am interested in finding a way to write all output that usually gets dumped to the console to a string. I could then send this string to myself and use it to debug the problem.
Is there a way to subscribe to all console output? I found runZoned(() => ...) but this seems to only collect certain logs and especially no logs from other isolates.
In theory, it's possible to capture all log output and then store it as a variable. In practice, it's a lot of work and will likely require elevated privileges to access the log stream from within the app itself (which might not even be possible on iOS without a rooted device).
However, I propose that you flip the equation - instead of retrieving the log output, capture your logs before they make it to the console in the first place.
This is where packages such as logger shine. By routing all of your print statements through a logging service, you can set up middleware that will capture your output on the way through the pipe. This way, you can store all of the output without having to mess with things like OS permissions and privileges.
final buffer = BufferOutput();
final logger = Logger(output: buffer);
class BufferOutput extends LogOutput {
final lines = <String>[];
#override
void output(OutputEvent event) {
lines.addAll(event.lines);
for (var line in event.lines) {
print(line);
}
}
}
Usage:
logger.v("This is verbose text");
logger.d("This is debug text");
logger.i("This is info text");
logger.w("This is warning text");
logger.e("This is error text");
logger.wtf("This is what-the-fudgestickles text");
print(buffer.lines);
// Output:
// ["This is verbose text","This is debug text","This is info text","This is warning text","This is error text","This is what-the-fudgestickles text"]
Note: This will work if you want to capture normal app logging output. If you want to automatically capture exceptional log output, you are better off using something like Crashlytics or Sentry to capture and collate those error logs for you since, depending on the error, you can't depend on your app code to be able to run after the error happens anyway.

Crash inside http_client constructor (Casablanca SDK)

I'm trying to use Casablanca to consume a REST api.
I've been following the microsoft tutorial, how ever i'm getting a crash and I cannot figure it out.
I'm using visual studio 2017 with C++11
I've codded a function GetRequest() that do work when used in a new empty project, but when I try to use it on my Project (Very big project with millions of code lines).
I'm crashing in the constructor of http_client, in the file xmemory0 line 118.
const uintptr_t _Ptr_container = _Ptr_user[-1];
This is a link to the callstack : https://i.imgur.com/lBm0Hv7.png
void RestManager::GetRequest()
{
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("XXX/XXX.svc/"));
// Build request URI and start the request.
uri_builder builder(U("/IsLive"));
builder.append_query(U("q"), U("cpprestsdk github"));
return client.request(methods::GET, builder.to_string());
})
// Handle response headers arriving.
.then([=](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
// Write response body into the file.
return response.body().read_to_end(fileStream->streambuf());
})
// Close the file stream.
.then([=](size_t)
{
return fileStream->close();
});
// Wait for all the outstanding I/O to complete and handle any exceptions
try
{
requestTask.wait();
}
catch (const std::exception &e)
{
printf("Error exception:%s\n", e.what());
}
}
EDIT : I just want to add that the http_client constructor is the issue. It always crash inside it no matter what I send as parameter.
The wierd thing is that it's not crashing when i just make a main() that call this function.
I guess it must be due to some memory issues, however I have no idea how could I debug that.
Does anyone would have an idea about it?
Thanks and have a great day!
I've experienced a similar issue on ubuntu. It works in an empty project, but crashes randomly when put into an existing large project, complaining memory corruptions.
Turns out that the existing project loaded a proprietary library, which is using cpprestsdk (casablanca) internally. Even cpprestsdk is static linked, its symbols are still exported as Weak Symbols. So either my code crashes, or the proprietary library crashes.
Ideally, my project can be divided into several libraries, and load them with RTLD_LOCAL to avoid symbol clashes. But the proprietary library in my project only accept RTLD_GLOBAL, otherwise it crashes... So the import order and flags become important:
dlopen("my-lib-uses-cpprest", RTLD_LOCAL); //To avoid polluting the global
dlopen("proprietary-lib-with-built-in-cpprest", RTLD_GLOBAL); //In my case, this lib must be global
dlopen("another-lib-uses-cpprest", RTLD_DEEPBIND); //To avoid being affected by global
"it will probably never concern anyone."
I agree with that.
I guess this issues was very specific, and it will probably never concern anyone, but still I'm going to update on everything I found out about it.
On this project, we are using custom allocator, if i'm not wrong, it's not possible to give our custom allocator to this lib, which result to many random crash.
A good option to fix it would be to use the static version to this lib, however, since we are using a lot of dynamic lib, this option wasn't possible for us.
If you are on my case, I would advice to use the libcurl and rapidjson, it's a bit harder to use, but you can achieve the same goal.

assert.async() never fails

I am new to OpenUI5/QUnit testing. Sorry for the newbie question.
I have added a very basic async QUnit test into my OpenUI5 project:
QUnit.test( "Test async", function( assert ) {
var done = assert.async();
setTimeout(function() {
assert.ok(true);
done();
});
});
This test passes without errors as expected.
Then I have commented out everything except for
var done = assert.async();
The test runs indefinitely without failing. I would expect that it fails after some timeout.
Pressing the "Abort" button just changes the label to "Aborting" but does not fail the test.
I have search the QUnit documentation, that suggest adding
assert.timeout( 1000 ); // Timeout of 1 second
that should be an equivalent to global setting
QUnit.config.testTimeout( 1000 );
But using either crash my test with
assert.timeout is not a function
or
QUnit.config.testTimeout is not a function
I have tried running the test in Chrome, Firefox and IE11 with the same results.
Can anyone tell me what I am doing wrong?
I have found the answer myself. The correct syntax is:
QUnit.config.testTimeout = 1000;
It is then valid for all the subsequent tests. Alternatively I can write
assert.timeout(1000);
at the beginning of the test method - must be before assert.async()

How to make Protractor's browser.wait() more verbose?

In Protractor tests I call many times browser.wait method for example to wait once the particular element will appear on the screen or it will be clickable.
In many cases tests passes on my local machine, but does not on other.
I receive very generic information about the timeout which doesn't help me a lot to debug / find a source of issue.
Is it possible to make a browser.wait more verbose, for example:
if at least defaultTimeoutInterval will elapse when waiting for particular element, will it be possible to console.log information about the element that it tried to wait for,
take a screenshot when the timeout error occurs,
provide full call stack when timeout appears in browser.wait
If the main issue is that you don't know for which element the wait timed out, I would suggest writing a helper function for wait and use it instead of wait, something like:
wait = function(variable, variableName,waitingTime){
console.log('Waiting for ' + variableName);
browser.wait(protractor.ExpectedConditions.elementToBeClickable(variablename),waitingTime);
console.log('Success');
}
Because protractor stops executing test after first fail, if wait timed out, console won't print success message after failing to load a certain element.
For screenshots I suggest trying out protractor-jasmine2-screenshot-reporter, it generates an easily readable html report with screenshots and debug information on failed tests (for example, in which code line the failure occured).
Look into using protractor's Expected Condition, you can specify what to wait for and how long to wait for it.
For screenshots there are npm modules out there that can take a screenshot when a test fails. This might help.
browser.wait returns a promise, so catch the error and print/throw something meaningful like:
await browser.wait(ExpectedConditions.visibilityOf(css), waitingTime).catch((error) =>
{
throw new CustomError(`Could not find ${css} ${error.message}`)
});

Await insert to finish before asserting

I have a model and wrote tests before I started. Now my problem is: While the functionality works, my tests are non-deterministic. Most of the time they work, but sometimes they don't. I assume it's because of the Future
But let's show you what I mean by example:
before {
db.run(animals.createTable)
}
after {
db.run(animals.dropTable)
}
"An animal" must "have a unique id" in
{
val setup = DBIO.seq(
animals.insert(Animal("Ape")),
animals.insert(Animal("Dog"))
)
db.run(setup)
val result = db.run(animals.tableQuery.result).futureValue
result shouldBe a[Seq[_]]
result distinct.length shouldEqual 2
result(0).id should not equal result(1).id
}
I assume sometimes the db.run(setup) finishes in time, but sometimes it does not, hence I then get an AssertionException "expected length was 2, actual 0". As said, to me it looks like a "race condition" here (I know that is not the correct terminus ;)).
So, what I tried was simply awaiting the result of the insert-statement like so:
Await.ready(db.run(setup), Duration.Inf)
But that doesn't change a thing. So why is that? Can somebody explain to me why Await does not block here? I assumed this to block and only execute the lines that come after, when the insert had been executed.
I also tried wrapping the assertions in an .onComplete-block, but no luck either.
Any hints for me?
I suspect your issue is that sometimes your before hook has not finished either, since it's also async. I would suspect that if you add an Await.ready to your future in the before block along with your setup block, the problem will go away.