How do I 'mock' the behavior of child widgets in Flutter widget tests? - flutter-test

Here is my dilemma: I'm writing widget tests for some custom widget in Flutter.
class ParentView extends StatefulWidget {
final NetworkCall networkCall;
final SomeExternalResource resource;
ParentView({this.networkCall, this.resource});
#override
State<StatefulWidget> createState() => _ParentViewState();
}
class _ParentViewState extends State<ParentView> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: AnotherCustomView(),
)
}
}
It's easy to mock the behavior of network calls and other classes, but what about a child widget -- AnotherCustomView in this case. Let's say it also has external calls it's making, and even custom children of its own. It seems impractical to have to consider all these dependencies every time I test any widget. What can I do to solve this problem?

Related

How to get the PerformContext from hangfire API

In our project we are using aspnetzero template. This template allows a simple but abstracted usage of hangfire. Now we would like to add Hangfire.Console to our project which would allow us to write logs to hangfires dashboard.
In order to write a log statement to the dashboard console we have to access the PerformContext of the current running job. Unfortunately because of the abstraction in aspnetzero we can't inject the PerformContext as it would be planned by hangfire. What we do have access to is the hangfire namespace and all it's static objects.
Therefore my question: Is there a way to get the PerformContext by another way than passing null to the execution method?
What I have tried so far:
By using the IServerFilter interface a method OnPerforming should be called. But unfortunately this is not the case within aspnetzero background jobs.
I tried to overwrite/extend the given base class BackgroundJob< T > of aspnetzero but with no luck. Perhaps someone can give me a hint in this direction.
I used JobFilterAttribute with a IServerFilter.
Example:
[AttributeUsage(AttributeTargets.Class)]
public class HangFirePerformContextAttribute : JobFilterAttribute, IServerFilter
{
private static PerformContext _Context;
public static PerformContext PerformContext
{
get
{
return new PerformContext(_Context);
}
}
public void OnPerformed(PerformedContext filterContext)
{
Context = (PerformContext)filterContext;
_Context = Context;
}
public void OnPerforming(PerformingContext filterContext)
{
Context = (PerformContext)filterContext;
_Context = Context;
}
}
And I create a new Class AsyncBackgroundJobHangFire<TArgs> : AsyncBackgroundJob<TArgs>
Exemple:
[HangFirePerformContext]
public abstract class AsyncBackgroundJobHangFire<TArgs> : AsyncBackgroundJob<TArgs>
{
public PerformContext Context { get; set; }
protected async override Task ExecuteAsync(TArgs args)
{
Context = HangFirePerformContextAttribute.PerformContext;
await ExecuteAsync(args, Context);
}
protected abstract Task ExecuteAsync(TArgs args, PerformContext context);
}
It´s Work
In a Class of job i use a AsyncBackgroundJobHangFire
And de method is
[UnitOfWork]
protected override async Task ExecuteAsync(string args, PerformContext context)
{
}
I have suffered using abp's implementation of hangfire jobs as well. I don't know how to answer your question precisely, but I was able to access a PerformingContext by implementing an attribute that extends JobFilterAttribute and implements IClientFilter, IServerFilter, IElectStateFilter, IApplyStateFilter. The interfaces will depend on your requirements, but I was capable of accessing PerformingContext this way.
You should never use a static field for that, even if marked with a ThreadStaticAttribute , please refer to this link for more details
https://discuss.hangfire.io/t/use-hangfire-job-id-in-the-code/2621/2

This class inherits from a class marked as #immutable, and therefore should be immutable (all instance fields must be final)

Getting the below issue, and not able to solve it, Can anyone help me in solving this.
This class inherits from a class marked as #immutable, and therefore should be immutable (all instance fields must be final). dart(must_be_immutable)
Thanks.
This issue occurs when all the class variables are not declared as final. You can either make them final or for ignoring this warning you can add the following comment above the class declaration:
//ignore: must_be_immutable
All fields in a class extending StatelessWidget should be final.
From the documentations.
StatelessWidget class. A widget that does not require mutable state.
https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html
Make sure that all your instances variable in class are marked as final and the object is also marked as final.
In class
class Items {
final String title;
final String author;
final String event;
final String img;
Items({this.title, this.author, this.event, this.img});
}
Inside widget that you in,
final Items item2 = new Items(
title: "Country",
author: "Balaji",
event: "4 Items",
img: "assets/panda.png",
);
Use That way
class Frog extends StatelessWidget {
const Frog({
Key key,
this.color = const Color(0xFF2DBD3A),
this.child,
}) : super(key: key);
final Color color;
final Widget child;
#override
Widget build(BuildContext context) {
return Container(color: color, child: child);
}
}
From flutter doc:
The following is a skeleton of a stateless widget subclass called GreenFrog.
Normally, widgets have more constructor arguments, each of which corresponds to a final property.
Just like this
class IconContainer extends StatelessWidget {
final double size;
final Color color;
final IconData icon;
IconContainer(this.icon, {this.color=Colors.white, this.size=32});
Widget build(BuildContext context) {
//TODO...
}
Any an immutable class add after it "final" to next line of flutter code, this will solve your problem,
For example:-
class Register extends statelesswidget {
static const string idScreen = 'register';
final TextEditingController name = TextEditingController();
final TextEditingController email = TextEditingController();
}
Maybe this will be helpful to someone else:
I am new to Flutter and I ran into this issue recently. I couldn't set my variables as final, though, because I needed to be able to change the values of the variables. I found out that in my case I needed to use a StatefulWidget instead of a StatelessWidget.
Simply add this line top of the warning:
//ignore: must_be_immutable
The problem is you cannot make the class immutable with out making all its properties 'final'. Sometimes we have to make a property not required and have to remove final. In this case your class never be immutable. You can simply ignore the warning. this will not harm your performance.

Libgdx, Why Should I Use Constructors When Switching Screens?

I am a beginner in libgdx and was wondering in what cases you would need to use a constructor when switching screens (examples would be helpful). Is it to save memory? Also, is it better to create instances of all the screens in the main class that extends the game?
Here is an example of instances from https://code.google.com/p/libgdx-users/wiki/ScreenAndGameClasses :
public class MyGame extends Game {
MainMenuScreen mainMenuScreen;
AnotherScreen anotherScreen;
#Override
public void create() {
mainMenuScreen = new MainMenuScreen(this);
anotherScreen = new AnotherScreen(this);
setScreen(mainMenuScreen);
}
}
The constructor is in the next class:
public class MainMenuScreen implements Screen {
MyGame game; // Note it's "MyGame" not "Game"
// constructor to keep a reference to the main Game class
public MainMenuScreen(MyGame game){
this.game = game;
}
...
You should avoid creating all screens in Game class in create() method (you will allocate much memory at once and pointlesly). Create only one screen at a time when do you need It. So e.g. you click button New game in menu and there you call game.setScreen(new NextScreen(this));
You do not have to make constructor with Game parameter - but you will not have reference to the main Game class. Having reference to main game class is good for changing screens, method setScreen(screen).
You need the constructor because your changing to a screen that doesnt extend the Game class which is what u need to call setScreen(); Since ur passing the game class to the constructor you can use it to get back to the screen you were at (or another screen) without creating another class that extends Game
I prefer using a singleton.
Something like
public class MyGame extends Game {
private static MyGame myGame;
public static MyGame getInstance() {
if (myGame == null) {
myGame = new MyGame();
}
return myGame;
}
#Override
public void create() {
setScreen(new MainMenuScreen();
}
}
And the example for desktop main class
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.width = 800;
cfg.height = 480;
new LwjglApplication(MyGame.getInstance(), cfg);
}
}
Now whenever you need to change your screen use MyGame.getInstance().setScreen(new ScreenName());

Libgdx multiple screens

Thanks to the help I got with my other problems on this forum, I managed to advance my project, but yet another obstacle appears in my way.
I am having trouble implementing multiple Screens in libgdx for java. I would like to know how can I implement multiple screens (one for the main menu, one for play, one for loading screen, ...).
An example or some explanations of how should I structure my screen classes would be really helpful. I tried implementing my own screen manager but that didn't go very well... Also some pointers on how should I dispose screens, since creating screens every time you go from main menu to play or to options menu isn't a very good idea. Any ideas or code example or advice is much appreciated.
What I have now are some classes of game screens which when you render them they will draw some GUI on the screen, but functions like the back button don't work since I don't know how to make the link between them.
Let's say you got 3 screens, MainMenuScreen, OptionsScreen, GameScreen.
First you need to declare them in your main class.
It will look like this
public class MainClass extends Game implements ApplicationListener {
private GameScreen gameScreen;
private MenuScreen menuScreen;
private OptionsScreen optionsScreen;
#Override
public void create() {
}
setGameScreen()
{
gameScreen=new GameScreen(this);
setScreen(gameScreen);
}
setMenuScreen()
{
menuScreen=new menuScreen(this);
setScreen(menuScreen);
}
setOptionsScreen()
{
optionsScreen=new OptionsScreen(this);
setScreen(gameScreen);
}
#Override
public void dispose() {
super.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
super.render();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void pause() {
super.pause();
}
#Override
public void resume() {
super.resume();
}
}
Now every screen you got, needs to have a MainClass variable and a constructor of it.
Lets say for the GameScreen class, it will be like
public class GameScreen implements Screen{
private MainClass mainClass;
public GameScreen(MainClass mc)
{
mainClass=mc;
}
// your methods (show,render, pause, etc)
}
Now when you want to change the screen just use in your screen
mainClass.setMenuScreen();

BlackBerry - Fun with FieldManagers

I am trying to make a View class that provides a Horizontal or Vertical layout depending on how it is created. I'm using a delegate to achieve this.
class View extends Manager {
private Manager mDelegate;
public View(Manager inDelegate) {
mDelegate = inDelegate;
// the delegate is the only child of "this" manager.
super.add(mDelegate);
}
public void add(Field f) {
// all other children go into the delegate.
mDelegate.add(f);
}
// other methods that also delegate
}
When I instantiate a View object I pass in a Horizontal or Vertical field manager and then delegate calls to that. This is kinda what the Screen class does in blackberry.
Actually I am looking at the blackberry docs for Screen to see what calls it delegates (so I can emulate that) and I notice calls like this in Screen...
protected boolean keyChar(char c, int status, int time)
Delegates key generation event to the controlled field with focus.
This method invokes Manager.keyChar(char, int, int) on this screen's delegate manager.
So then it immediately dawns on me, how in the world are they calling a protected method on the screen's delegate? Or are the docs wrong and this method isn't delegated?
Anyone know how they accomplish this?
Reminding myself what protected means:
A protected method can be called by
any subclass within its class, but not
by unrelated classes.
This doesn't directly answer your question, but could you extend Screen (API here) instead of Manager and then call super(mDelegate) in your constructor? Then presumably whatever magic is necessary will just work?
Aside from that I would just suggest you try it and see if you can override the supposedly protected method!
I managed to work out a solution to this problem with help from some other SO questions.
My solution is to create an interface that provides the public access points for the protected methods and then subclass the Manager class and mix in that interface. The public method will then call its super's protected method.
Then the View class is then passed one of these Manager subclasses.
public interface ManagerDelegate {
Manager asManager();
// Provide public access points to any protected methods needed.
void doProtectedMethod();
}
public HorizontalDelegate extends HorizontalFieldManager implements ManagerDelegate {
public Manager asManager() {
return this;
}
public void doProtectedMethod() {
// call the Manager's protected method.
protectedMethod();
}
}
public VerticalDelegate extends VerticalFieldManager implements ManagerDelegate {
public Manager asManager() {
return this;
}
public void doProtectedMethod() {
// call the Manager's protected method.
protectedMethod();
}
}
public class View extends Manager {
private final ManagerDelegate mDelegate;
public View(ManagerDelegate inDelegate) {
mDelegate = inDelegate;
}
protected void protectedMethod() {
// Call into our delegate's public method to access its protected method.
mDelegate.doProtectedMethod();
}
public void publicMethod() {
// For public delegated methods I can just get the Manager instance from
// the delegate and call directly.
mDelegate.asManager().publicMethod();
}
}

Resources