I am migrating an app to glide v4.7.1 from v3 and have noticed that FifoPriorityThreadPoolExecutor class was removed. We use it to limit number of threads Glide use to do network operations.
Old code
public class GlideConfiguration implements GlideModule {
#Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setResizeService(new FifoPriorityThreadPoolExecutor(1));
}
...
}
New code
#GlideModule
public class MyAppGlideModule extends AppGlideModule {
private static final String FIFO_SOURCE_EXECUTOR_NAME = "fifo-source";
#Override
public void applyOptions(#NonNull Context context, #NonNull GlideBuilder builder) {
builder.setSourceExecutor(newSourceExecutor(1, FIFO_SOURCE_EXECUTOR_NAME, GlideExecutor.UncaughtThrowableStrategy.DEFAULT));
}
...
}
But it still uses 4 threads. What am I doing wrong?
After checking glide's source code.
Glide will initialize its default source executor only if no source executor has been provided to builder.
Glide build(#NonNull Context context) {
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
...
}
// Glide executor is simply a wrapper over ThreadPoolExecutor class.
public static GlideExecutor newSourceExecutor(int threadCount, String name, UncaughtThrowableStrategy uncaughtThrowableStrategy) {
return new GlideExecutor(new ThreadPoolExecutor(threadCount /* corePoolSize */,threadCount /* maximumPoolSize */,0 /* keepAliveTime */,TimeUnit.MILLISECONDS,new PriorityBlockingQueue<Runnable>(),new DefaultThreadFactory(name, uncaughtThrowableStrategy, false)));
}
Since you are inspecting threads using Stetho library to monitor network call which doesn't show any information about threads. It's very likely that these requests are being initiated by single thread.
To better understand thread usage in app, you should inspect it using Android monitor -> DDMS -> Threads.
I have checked using DDMS Threads tool and found only one thread running with mentioned code snippet.
Related
the below posted method in the code section contains a static method which is "with()". I want to test the code in below, so I coded the test of this method
as shown in the testing section.
i tried to test the method using both of "spy()" and "mock()" but the test fails alwyas.
please let me know how can I test a method returns void?
code
public RequestCreator requestCreatorFromUrl(String picUrl) {
return Picasso.with(mCtx).load(picUrl);
}
testing:
public class ValidationTest {
#Mock
private Context mCtx = null;
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Before
public void setUp() throws Exception {
mCtx = Mockito.mock(Context.class);
Assert.assertNotNull("Context is not null", mCtx);
}
#Test
public void whenRequestCreatorFromUrlTest() throws Exception {
Picasso picasso = Picasso.with(mCtx);
Picasso spyPicasso = spy(picasso);
Uri mockUri = mock(Uri.class);
RequestCreator requestCreator = Picasso.with(mCtx).load(mockUri);
RequestCreator spyRequestCreator = spy(requestCreator);
doReturn(spyRequestCreator).when(spyPicasso.load(mockUri));
//when(spyPicasso.load(mockUri)).thenReturn(spyRequestCreator);
RequestCreator actual = spyPicasso.load(mockUri);
Assert.assertEquals(requestCreator, actual);
}
Usually, if you end up using PowerMock, that’s a good sign that you most possibly are on the wrong way.
What if instead of directly referring to Picasso, you create a component, whose responsibility will be to load an image, let's say class ImageLoader. What will this give to you?
Separation of concerns: if tomorrow you decide to move to Glide, you shouldn't change each and every class where you were using Picasso, you will just change implementation of ImageLoader. Other components are non-wiser of these changes, because they are dependent on an abstraction, not on implementation
Seam: this will allow you easily mock dependencies in order to perform unit testing
This will be our abstraction:
interface ImageLoader {
RequestCreator load(String url);
}
Let’s provide an implementation:
class ImageLoaderImpl implements ImageLoader {
private final Picasso picasso;
public ImageLoaderImpl(Context context) {
this.picasso = Picasso.with(context);
}
#Override
public RequestCreator load(String url) {
return picasso.load(url);
}
}
Now, in your components whenever you need Picasso use ImageLoader instead.
Thus, your method becomes following:
public static RequestCreator requestCreatorFromUrl(String picUrl) {
return imageLoader.load(picUrl);
}
Then your test will look like this:
#Test
public void test() {
ImageLoaderImpl imageLoader = Mockito.mock(ImageLoaderImpl.class);
RequestCreator expected = Mockito.mock(RequestCreator.class);
String TEST_URL = "https://www.some.url/img.jpg";
when(imageLoader.load(TEST_URL)).thenReturn(expexted);
RequestCreator actual = clazzToTest.requestCreatorFromUrl(TEST_URL);
assertEquals(expected, actual);
}
No mocking of static method, no PowerMock needed.
From the Mockito's FAQ:
What are the limitations of Mockito
...
Cannot mock static methods
Use PowerMock instead. Here you will find the detailed instruction about how to mock the static methods.
Update
In order to apply the PowerMock to your test you need to:
Add #PrepareForTest at test class level:
#PrepareForTest(Picasso.class)
public class ValidationTest {
...
}
Call PowerMockito.mockStatic() to mock a static class
PowerMockito.mockStatic(Picasso.class);
Just use Mockito.when() to setup your expectation:
Mockito.when(Picasso.with(mCtx)).thenReturn(requestCreator);
The same set of steps is applicable for the RequestCreator.class.
P.S. I can make mistakes because I do not know the API of 3rd party library you use.
Mockito creates a proxy instance when some thing is spied on. Now, is there any way to forward setters that are then executed on that proxy instance to the real instance that sits behind it?
Rationale: I have an object instance that I do not have completely under my control, i.e. an Android activity. I can give most parts of my app the proxied version and that runs fine as is, but because I need to create the spy / proxy very early during the creation phase of the activity, it is not yet fully instantiated, e.g. the base context is not attached. This happens on the proxy instance and is of course not used by the activity instance itself (which refers to itself via Activity.this). The end result is that this leads to all kinds of crashes because resource resolving happens via this base context, so the internal Fragment machinery throws NPEs and more.
Here is some code:
public class CustomAndroidJUnitRunner extends AndroidJUnitRunner {
#Override
public Activity newActivity(ClassLoader cl, String className, Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Activity activity = super.newActivity(cl, className, intent);
return maybeStubSomeDelegate(activity);
}
private Activity maybeStubSomeDelegate(Activity activity) {
if (!(activity instanceof SomeDelegate)) {
return activity;
}
Activity spiedActivity = spy(activity);
doReturn(SomeDelegateMock.getInstance())
.when((SomeDelegate) spiedActivity)
.getDelegate();
return spiedActivity;
}
}
I'm clueless - any ideas?
Using:
android Test Support library's
SingleActivityFactory,
ActivityTestRule
and Mockito's
spy()
dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'org.mockito:mockito-android:2.21.0'
}
Outline:
inject the spied instance inside SingleActivityFactory's implementation
Code:
public class MainActivityTest {
MainActivity subject;
SingleActivityFactory<MainActivity> activityFactory = new SingleActivityFactory<MainActivity>(MainActivity.class) {
#Override
protected MainActivity create(Intent intent) {
subject = spy(getActivityClassToIntercept());
return subject;
}
};
#Rule
public ActivityTestRule<MainActivity> testRule = new ActivityTestRule<>(activityFactory, true, true);
#Test
public void activity_isBeingSpied() {
verify(subject).setContentView(R.layout.activity_main);
}
}
You can use Robolectric to create your own proxy (or as Robolectric calls them "Shadows") to your activity,
When you create the proxy you can create your own setters that can trigger the real object methods,
How to create a shadow example:
#Implements(Bitmap.class)
public class MyShadowBitmap {
#RealObject private Bitmap realBitmap;
private int bitmapQuality = -1;
#Implementation
public boolean compress(Bitmap.CompressFormat format, int quality, OutputStream stream) {
bitmapQuality = quality;
return realBitmap.compress(format, quality, stream);
}
public int getQuality() {
return bitmapQuality;
}
}
}
when the #RealObject is your real instance,
To use this shadow using Robolectric test runner define a new test class as follows:
#RunWith(RobolectricTestRunner.class)
#Config(shadows = MyShadowBitmap.class)
public class MyTestClass {}
To pull the current shadow instance use the method:
shadowOf()
And in any case, here is s link to Robolectric:
http://robolectric.org/custom-shadows/
I've recently gone whole-hog with Dagger because the concept of DI makes complete sense. One of the nicer "by-products" of DI (as Jake Wharton put in one of his presentations) is easier testability.
So now I'm basically using Espresso to do some functional testing, and I want to be able to inject dummy/mock data to the application and have the activity show them up. I'm guessing since, this is one of the biggest advantages of DI, this should be a relatively simple ask. For some reason though, I can't seem to wrap my head around it. Any help would be much appreciated. Here's what I have so far (I've written up an example that reflects my current setup):
public class MyActivity
extends MyBaseActivity {
#Inject Navigator _navigator;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApplication.get(this).inject(this);
// ...
setupViews();
}
private void setupViews() {
myTextView.setText(getMyLabel());
}
public String getMyLabel() {
return _navigator.getSpecialText(); // "Special Text"
}
}
These are my dagger modules:
// Navigation Module
#Module(library = true)
public class NavigationModule {
private Navigator _nav;
#Provides
#Singleton
Navigator provideANavigator() {
if (_nav == null) {
_nav = new Navigator();
}
return _nav;
}
}
// App level module
#Module(
includes = { SessionModule.class, NavigationModule.class },
injects = { MyApplication.class,
MyActivity.class,
// ...
})
public class App {
private final Context _appContext;
AppModule(Context appContext) {
_appContext = appContext;
}
// ...
}
In my Espresso Test, I'm trying to insert a mock module like so:
public class MyActivityTest
extends ActivityInstrumentationTestCase2<MyActivity> {
public MyActivityTest() {
super(MyActivity.class);
}
#Override
public void setUp() throws Exception {
super.setUp();
ObjectGraph og = ((MyApplication) getActivity().getApplication()).getObjectGraph().plus(new TestNavigationModule());
og.inject(getActivity());
}
public void test_SeeSpecialText() {
onView(withId(R.id.my_text_view)).check(matches(withText(
"Special Dummy Text")));
}
#Module(includes = NavigationModule.class,
injects = { MyActivityTest.class, MyActivity.class },
overrides = true,
library = true)
static class TestNavigationModule {
#Provides
#Singleton
Navigator provideANavigator() {
return new DummyNavigator(); // that returns "Special Dummy Text"
}
}
}
This is not working at all. My Espresso tests run, but the TestNavigationModule is completely ignored... arr... :(
What am I doing wrong? Is there a better approach to mocking modules out with Espresso? I've searched and seen examples of Robolectric, Mockito etc. being used. But I just want pure Espresso tests and need to swap out a module with my mock one. How should i be doing this?
EDIT:
So I went with #user3399328 approach of having a static test module list definition, checking for null and then adding it in my Application class. I'm still not getting my Test injected version of the class though. I have a feeling though, its probably something wrong with dagger test module definition, and not my espresso lifecycle. The reason I'm making the assumption is that I add debug statements and find that the static test module is non-empty at time of injection in the application class. Could you point me to a direction of what I could possibly be doing wrong. Here are code snippets of my definitions:
MyApplication:
#Override
public void onCreate() {
// ...
mObjectGraph = ObjectGraph.create(Modules.list(this));
// ...
}
Modules:
public class Modules {
public static List<Object> _testModules = null;
public static Object[] list(MyApplication app) {
// return new Object[]{ new AppModule(app) };
List<Object> modules = new ArrayList<Object>();
modules.add(new AppModule(app));
if (_testModules == null) {
Log.d("No test modules");
} else {
Log.d("Test modules found");
}
if (_testModules != null) {
modules.addAll(_testModules);
}
return modules.toArray();
}
}
Modified test module within my test class:
#Module(overrides = true, library = true)
public static class TestNavigationModule {
#Provides
#Singleton
Navigator provideANavigator()() {
Navigator navigator = new Navigator();
navigator.setSpecialText("Dummy Text");
return navigator;
}
}
With Dagger 2 and Espresso 2 things have indeed improved. This is how a test case could look like now. Notice that ContributorsModel is provided by Dagger. The full demo available here: https://github.com/pmellaaho/RxApp
#RunWith(AndroidJUnit4.class)
public class MainActivityTest {
ContributorsModel mModel;
#Singleton
#Component(modules = MockNetworkModule.class)
public interface MockNetworkComponent extends RxApp.NetworkComponent {
}
#Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
MainActivity.class,
true, // initialTouchMode
false); // launchActivity.
#Before
public void setUp() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
RxApp app = (RxApp) instrumentation.getTargetContext()
.getApplicationContext();
MockNetworkComponent testComponent = DaggerMainActivityTest_MockNetworkComponent.builder()
.mockNetworkModule(new MockNetworkModule())
.build();
app.setComponent(testComponent);
mModel = testComponent.contributorsModel();
}
#Test
public void listWithTwoContributors() {
// GIVEN
List<Contributor> tmpList = new ArrayList<>();
tmpList.add(new Contributor("Jesse", 600));
tmpList.add(new Contributor("Jake", 200));
Observable<List<Contributor>> testObservable = Observable.just(tmpList);
Mockito.when(mModel.getContributors(anyString(), anyString()))
.thenReturn(testObservable);
// WHEN
mActivityRule.launchActivity(new Intent());
onView(withId(R.id.startBtn)).perform(click());
// THEN
onView(ViewMatchers.nthChildOf(withId(R.id.recyclerView), 0))
.check(matches(hasDescendant(withText("Jesse"))));
onView(ViewMatchers.nthChildOf(withId(R.id.recyclerView), 0))
.check(matches(hasDescendant(withText("600"))));
onView(ViewMatchers.nthChildOf(withId(R.id.recyclerView), 1))
.check(matches(hasDescendant(withText("Jake"))));
onView(ViewMatchers.nthChildOf(withId(R.id.recyclerView), 1))
.check(matches(hasDescendant(withText("200"))));
}
Your approach doesn't work because it only happens once, and as Matt mentioned, when the activity's real injection code runs, it will wipe out any variables injected by your special object graph.
There are two ways to get this to work.
The quick way: make a public static variable in your activity so a test can assign an override module and have the actual activity code always include this module if it's not null (which will only happen in tests). It's similar to my answer here just for your activity base class instead of application.
The longer, probably better way: refactor your code so that all activity injection (and more importantly graph creation) happens in one class, something like ActivityInjectHelper. In your test package, create another class named ActivityInjectHelper with the exact same package path that implements the same methods, except also plusses your test modules. Because test classes are loaded first, your application will execute with the testing ActivityInjectHelper. Again it's similar to my answer here just for a different class.
UPDATE:
I see you've posted more code and it's close to working, but no cigar. For both activities and applications, the test module needs to be snuck in before onCreate() runs. When dealing with activity object graphs, anytime before the test's getActivity() is fine. When dealing with applications, it's a bit harder because onCreate() has already been called by the time setUp() runs. Luckily, doing it in the test's constructor works - the application hasn't been created at that point. I briefly mention this in my first link.
The call to getActivity will actually start your activity calling onCreate in the process which means you won't be getting your test modules added to the graph in time to be used. Using activityInstrumentationTestcase2 you can't really inject properly at the activity scope. I've worked around this by using my application to provide dependencies to my activities and then inject mock objects into it which the activities will use. It's not ideal but it works. You can use an event bus like Otto to help provide dependencies.
EDIT: the below in post form http://systemdotrun.blogspot.co.uk/2014/11/android-testing-with-dagger-retrofit.html
To test an Activity using Espresso + Dagger I have done the below
Inspired by the answer from #user3399328 I have a DaggerHelper class inside my Application class, which allows the test case to override the #Providers using Test #Modules which supply mocks. As long as
1) This is done before the testCases getActivity() call is made (as my inject call happens in my activity inside Activity.onCreate)
2) tearDown removes the test modules from the object graph.
Examples below.
Note: this is not ideal as this is subject to similar pitfalls of using factory methods for IoC but at least this way its only ever a single call in tearDown() to bring the system under test back to normal.
The DaggerHelper inside my Application class
public static class DaggerHelper
{
private static ObjectGraph sObjectGraph;
private static final List<Object> productionModules;
static
{
productionModules = new ArrayList<Object>();
productionModules.add(new DefaultModule());
}
/**
* Init the dagger object graph with production modules
*/
public static void initProductionModules()
{
initWithModules(productionModules);
}
/**
* If passing in test modules make sure to override = true in the #Module annotation
*/
public static void initWithTestModules(Object... testModules)
{
initWithModules(getModulesAsList(testModules));
}
private static void initWithModules(List<Object> modules)
{
sObjectGraph = ObjectGraph.create(modules.toArray());
}
private static List<Object> getModulesAsList(Object... extraModules)
{
List<Object> allModules = new ArrayList<Object>();
allModules.addAll(productionModules);
allModules.addAll(Arrays.asList(extraModules));
return allModules;
}
/**
* Dagger convenience method - will inject the fields of the passed in object
*/
public static void inject(Object object) {
sObjectGraph.inject(object);
}
}
My Test module inside my test class
#Module (
overrides = true,
injects = ActivityUnderTest.class
)
static class TestDataPersisterModule {
#Provides
#Singleton
DataPersister provideMockDataPersister() {
return new DataPersister(){
#Override
public void persistDose()
{
throw new RuntimeException("Mock DI!"); //just a test to see if being called
}
};
}
}
Test method
public void testSomething()
{
MyApp.DaggerHelper.initWithTestModules(new TestDataPersisterModule());
getActivity();
...
}
Tear down
#Override
public void tearDown() throws Exception
{
super.tearDown();
//reset
MyApp.DaggerHelper.initProductionModules();
}
I have a library that I plan on using in dex form. I want to compile directly against this library, but not export it. Instead I want to drop it in my resources and use a class loader to actually instantiate it.
So here's my library:
public class Foo {
public doFoo(String message) {
}
public doFoo(int count, String message) {
}
}
Now I want to call doFoo(). A lot. More than it's probably reasonable to use reflection for. Right now it works with:
public class FooConsumer {
private final DexClassLoader fooLoader;
public FooConsumer(DexClassLoader fooLoader) {
this.fooLoader = fooLoader;
}
public void go() {
Class<?> fooClass = fooLoader.loadClass("com.library.Foo");
Object fooInstance = fooClass.newInstance();
Method fooMethodDoFoo = fooClass.getMethod("doFoo", String.class);
fooMethodDoFoo.invoke(fooInstance, "Hello World");
}
This is obviously fugly. Especially since I haven't included any of the exception handling, as there are half a dozen throwables to catch in there. I could cache a bunch of stuff, helping me with speed a bit, but not a lot.
Normally I'd have both aware of a third library that has an interface, but the library has some static methods and I can't edit it anyway. It'd be really nice if I could do something like:
public class FooConsumer {
private FooAccessor accessor;
public FooConsumer(DexClassLoader fooLoader) {
Object fooInstance = fooLoader.loadClass("com.library.Foo").newInstance();
Log.i("TEST", "fooInstance: " + fooInstance);
this.accessor = new FooAccessor(fooInstance);
}
public void go() {
accessor.doFoo("Hello World");
}
private static class FooAccessor {
private Foo fooInstance;
public FooAccessor(Object instance) {
fooInstance = (Foo)instance;
}
public void doFoo(String message) {
fooInstance.doFoo(message);
}
}
}
See what I did there? The inner class is just a wrapper around the Foo object, I've linked against it, but not exported it, and all is good in the world. But it doesn't work. In logcat I get
I/TEST: fooInstance: com.library.Foo#413b1b68
E/AndroidRuntime: java.lang.NoClassDefFoundError: com.library.Foo
...
Is there a way to have FooAccessor use the class loader I passed in? Or is the use of class loaders a damnation into reflection hell.
You might want to take a look at this gist.
https://gist.github.com/nickcaballero/7045993
It uses reflection to merge the new DexClassLoader to in-stock BaseDexClassLoader.
I am working on a project hosted on AppEngine, and for the browser client I am using the GWTP platform which implies using GIN (on the client) and GUICE on the server. Also, it uses Models, presenters, actions and events.
I am thinking of also writing an android client for the service but I don't know how to start because I don't know how to connect and exchange data with the webservice. I would have to use Actions and Action Handlers ( http://code.google.com/p/gwt-platform/wiki/GettingStartedDispatch ) which I use for the browser client. From Android I only know how to do it with RPC, and I can't make the connection, I don't know how to map classes from the device to the server.
For example, by using GWTP, if on the browser client I want to do something on the server, I implement an Action class, an ActionResult class ( both on the client ) and an ActionHandler class (on the server). To dispatch an action, I use the DispatchAsync interface and to get the result I use AsyncCallback.
Action (on the client ) - SendRoadNotification.java :
public class SendRoadNotification extends
ActionImpl<SendRoadNotificationResult> {
private RoadNotification roadNot;
#SuppressWarnings("unused")
private SendRoadNotification() {
// For serialization only
}
public SendRoadNotification(RoadNotification roadNot) {
this.roadNot = roadNot;
}
public RoadNotification getRoadNot() {
return roadNot;
}
}
ActionResult (on the client ) -- SendRoadNotfifcationResult.java :
public class SendRoadNotificationResult implements Result {
private RoadNotification roadNot;
#SuppressWarnings("unused")
private SendRoadNotificationResult() {
// For serialization only
}
public SendRoadNotificationResult(RoadNotification roadNot) {
this.roadNot = roadNot;
}
public RoadNotification getRoadNot() {
return roadNot;
}
}
ActionHandler ( on the server ) -- SendRoadNotificationActionHandler.java :
public class SendRoadNotificationActionHandler implements
ActionHandler<SendRoadNotification, SendRoadNotificationResult> {
static DataStore ds = DataStore.getDatastoreService();
#Inject
public SendRoadNotificationActionHandler() {
}
#Override
public SendRoadNotificationResult execute(SendRoadNotification action,
ExecutionContext context) throws ActionException {
//Here I am doing something with that action
}
#Override
public void undo(SendRoadNotification action,
SendRoadNotificationResult result, ExecutionContext context)
throws ActionException {
}
#Override
public Class<SendRoadNotification> getActionType() {
return SendRoadNotification.class;
}
}
The way I use those, is:
SendRoadNotification action = new SendRoadNotification(rn);
dispatchAsync.execute(action, sendRoadNotifCallback);
And the callback:
AsyncCallback<SendRoadNotificationResult> sendRoadNotifCallback = new AsyncCallback<SendRoadNotificationResult>() {
#Override
public void onSuccess(SendRoadNotificationResult result) {
}
#Override
public void onFailure(Throwable caught) {
Window.alert("Something went wrong");
}
};
How can I implement this in android ? Can somebody give me an example or had this problem before ?
I am using AppEngine sdk 1.6.4, GWT sdk 2.4.0, GWTP plugin for Eclipse and GPE plugin for Eclipse.
You might want to look at the source the GAE plugin for ADT generates for 'App Engine Connected Android apps' for inspiration. They are doing something similar by calling GWT endpoints using Android's HttpClient.
https://developers.google.com/eclipse/docs/appengine_connected_android