I am trying to understand how mocking works with dart and mockito.
Image I have the below declarations:
void foo(){}
and similarly a class
class BarClass {
void bar(){}
}
and then my widget accesses the first one directly as foo(); and the second one as BarClass().
What would be the way to mock these two? Should I be accessing them through something like getit to mock them properly or is there actually a way?
You can easily mock classes by creating a new class that implements the functionality of your old one using the mockito package
example code:
class MockBarClass extends Mock implements BarClass {}
you can mock methods of your BarClass in the following way:
final mock = MockBarClass();
when(() => mock.boo()).thenAnswer((_) {
// your mocked response
print("hello world");
});
you can mock functions that are in no classes the same way:
when(boo()).thenReturn();
source by Remi Rousselet
additional information if you ask yourself what's the difference between .thenReturn(...) and .thenAnswer((){...}):
I recommend reading this explanation: https://stackoverflow.com/a/36627077/12165405 (even though it's for java, the same applies for that flutter package)
Related
I am trying to understand the best practices in Dart and I saw in couple of instances that people declare singletons without the getit package and also the factory declarations are also a bit confusing for me. So let's assume I have these two classes below:
class Singleton {
static final Singleton _singleton = Singleton._internal();
factory Singleton() {
return _singleton;
}
Singleton._internal();
}
class RegularClass {
RegularClass();
}
I have two questions here:
What is the difference between
Singleton() and GetIt.I.registerSingleton<RegularClass>(() => RegularClass());
What is the difference between RegularClass() and GetIt.I.registerFactory<RegularClass>(() => RegularClass());
If these cases don't really matter, then what cases matter? What are the different use cases for these?
There is no real difference.
But as your app grows, using getIt (especially together with e.g. injectable) will make your app a lot easier to work with and save you a lot of time.
Edit (in response to requested elaboration):
As an example. Consider having a class setup as below, that use an API which you have setup as an interface (abstract class)
#Injectable
class MyClass {
MyClass(this.myApi);
final IApi myApi;
...
}
#LazySingleton(as: IApi)
class MyApi implements IApi {
...
}
You will then be able to let getIt and injectable solve these dependencies, factories and singletons where needed and appropriate, so that when you want to use e.g. MyClass, you don't have to consider what needs to be injected where, and what type of parameters that needs to be injected where.. All you have to call is:
final instaceOfMyClass = getIt<MyClass>();
And on top of this, if you want to have e.g. a Mock implementation of IApi, or a separate implementation for production and some test environment, you can define that with the annotations, so that your entire setup is handled based on one single input parameter when you launch your app. So, instead of what I wrote above for the singleton, you could as an example do two separate implementations of the API, and let getIt solve everything for you based on your environment. Meaning you can still just call getIt<MyClass>() to get MyClass, but your instance of IApi will differ based on your setup:
#LazySingleton(as: IApi, env: ['dev'])
class MyTestEnviromentApi implements IApi { ... }
#LazySingleton(as: IApi, env: ['prod'])
class MyProductionEnvironementApi implements IApi { ... }
Should I inject an interface or its implementation ?
I came across the below code in a tutorial and I am wondering why inject the interface but register it as its implementation when you can just directly inject its implementation?
SIGNINBLOC
#injectable
class SignInBloc extends Bloc<SignInEvent, SignInState> {
final IAuthFacade _authFacade;
SignInBloc(this._authFacade) : super(SignInState.initial());
FIREBASEAUTH
#LazySingleton(as: IAuthFacade)
class FirebaseAuthFacade implements IAuthFacade {
INJECTION CONFIG
gh.lazySingleton<IAuthFacade>(
() => FirebaseAuthFacade(get<FirebaseAuth>(), get<GoogleSignIn>()));
You want to separate the implementation details and dependency to a specific implementation. It will be easier to switch between different implementations and also easier to mock the interface when testing.
You can for example configure GetIt to use different implementations for the interface depending on if it is e.g. development environment, production environment, test environment etc.. You only have to change one line and it will change everywhere.
My goal is to import platform-specific code only on the respective platform. One use case is e.g. if the dart:html package is used in the imported file which isn't available on iOS. Another example for platform-specific Dart code: XHR HTTP request (only available in browser) vs. other HTTP client implementation.
Previous, failed attempts:
1)
import 'specific_to_web.dart' if (dart.library.html) '';
2)
import 'package:flutter/foundation.dart' show kIsWeb;
import 'specific_to_web.dart' if (kIsWeb) '';
3)
In the file I'm importing:
export 'api_channel_grpc_web.dart'
if (dart.library.html) 'api_channel_grpc_raw.dart';
This is also mentioned in Flutter issue Dart SDK libraries and Flutter for web.
The really clean and sustainable solution is to write a federated plugin. Plugins are not just for external use, for other people to consume as a library, you can easily put a plugin inside your own project to separate out platform specific code.
If you really don't want to do that because you only need a few items inside your own code, just set up the usual interface-implementation approach. You write an abstract class with the interface you want to use, you write two (or more) implementations and you include the one you need conditionally. An extract from one of my apps:
The interface:
// interface.dart
import 'worker.dart' //
if (dart.library.io) 'worker_io.dart'
if (dart.library.html) 'worker_async.dart';
abstract class BackgroundWorker {
factory BackgroundWorker() => getWorker();
void sendTo(dynamic message);
}
The base implementation:
// worker.dart
BackgroundWorker getWorker() => throw UnimplementedError('getWorker');
The mobile implementation:
// worker_io.dart
BackgroundWorker getWorker() => BackgroundWorkerIo();
class BackgroundWorkerIo implements BackgroundWorker {
#override
void sendTo(dynamic message) {
}
}
The web implementation:
// worker_web.dart
BackgroundWorker getWorker() => BackgroundWorkerWeb();
class BackgroundWorkerWeb implements BackgroundWorker {
#override
void sendTo(dynamic message) {
}
}
To use it, you simply call getWorker(), that will return the actual implementation needed, and you call its methods, functions, fields, whatever.
Oh, and while I didn't need it in this code of mine but if the implementations are not that lightweight and you want to avoid instantiating them again and again with every call to getWorker(), return a singleton instead.
I try to start unit testing a mid size Xtext project.
The generator currently relies on some external resources that I would like to mock inside my test. Thus, I inject the needed object via #Inject into the Generator class.
e.g in pseudocode:
class MyGenerator implements IGenerator{
#Inject
ExternalResourceInterface resourceInterface;
...
}
I create the actual binding inside the languages RuntimeModule:
class MyRuntimeModule{
...
#Override
public void configure(Binder binder) {
super.configure(binder);
binder.bind(ExternalResourceInterface .class).to(ExternalResourceProductionAcess.class);
}
...
}
This works fine for the production environment.
However, in the generator test case, I would like to replace the binding with my mocked version, so that the following call to the CompilationTestHelper uses the mock:
compiler.assertCompilesTo(dsl, expectedJava);
Question:
Where do I tell guice/Xtext to bind the injection to the mock?
If you annotate your test case with RunWith and InjectWith, your test class will be injected via a specific IInjectorProvider implementation.
If that injector provider uses a custom module (like you have shown), the test case gets injected using that configuration. However, you have to make sure you use this injector throughout the test code (e.g. you do not rely on a registered injector, etc.).
Look for the following code as an example (have not compiled it, but this is the base structure you have to follow):
#RunWith(typeof(XtextRunner))
#InjectWith(typeof(LanguageInjectorProvider))
public class TestClass {
#Inject
CompilationTestHelper compiler
...
}
I used to get the application.conf variable in Play 2.4.x with Play.current.configuration.getString('NAME_HERE'), and it was working good in class, object and companion object too.
Now, I'm using Play 2.5.4 with Scala in a new project, and I won't use this Play.current, because it's deprecated, but there is an alternative using DI, like this :
class HomeController #Inject() (configuration: play.api.Configuration) extends Controller {
def config = Action {
Ok(configuration.underlying.getString("db.driver"))
}
}
This DI Injection works like a charm in class, but in this project, I need to get the variable db.driver in a object? And as far I know, with an object I can't use DI.
Maybe using Guice would help?
You can use #Singleton annotated class instead of object
trait Foo {}
#Singleton
class FooImpl #Inject()(configuration: play.api.Configuration)) extends Foo {
//do whatever you want
}
#Singleton makes the class singleton.It feels bit awkward because Scala itself natively have syntax object to create a singleton, But this is the easiest and probably best solution to DI into a singleton.
You also may create the singleton eagerly like the code below.
bind(classOf[Foo]).to(classOf[FooImpl])asEagerSingleton()
for more detail Info, You can look up Google Guice Wiki and Playframework site
EDIT
How you call it is exactly the same as how you DI in Playframework2.5.
class BarController #Inject()(foo: Foo) extends Controller {
//Do whatever you want with Foo
}
Guice basically generates new instance every time you DI, Once you put #Singleton, Guice use only one instance instead.
DI is for anti-high coupling.So when you want to use a class you defined from another class,You need to DI otherwise the classes are highly coupled which end up making it harder to code your unit test.
FYI, You can use them outside of Play with this technique.
Create an Instance of class which does DI via Playframework Guice Independently in Scala
Have you tried
import com.typesafe.config.ConfigFactory
val myConfig = ConfigFactory.load().getString("myConfig.key")
Above approach doesn't require you to convert your object to singleton class.
You can do
Play.current.configuration
however that will (probably) no longer be possible with Play 2.6.
Ideally, however, you would pass the configuration in as a parameter to that method of the object or, use a class instead of an object.
What I somtimes do to migrate 'from object to class':
class MyComponent #Inject() (config: Configuration) {
// here goes everything nice
def doStuff = ???
}
object MyComponent {
#deprecated("Inject MyComponent")
def doStuff = {
val instance = Play.current.injector.instanceOf[MyComponent]
instance.doStuff
}
}
This way, you're not breaking existing code while all users of your methods can slowly migrate to using classes.