Giter Club home page Giter Club logo

Comments (6)

passsy avatar passsy commented on May 30, 2024

I never tested it with Robolectric but it doesn't look like a big problem.

You have to make sure that context.getString(R.string.tray__authority) (here context is the Application context) returns the correct authority. I'm not sure if Robolectric works with the generated.xml files which could cause this error.

Please check if mocking the string resource works.

RuntimeEnvironment.application = spy(RuntimeEnvironment.application);
when(RuntimeEnvironment.application.getApplicationContext())
    .thenReturn(RuntimeEnvironment.application);

Resources spiedResources = spy(app.getResources());
when(app.getResources())
    .thenReturn(spiedResources);

when(spiedResources.getString(R.string.tray__authority))
    .thenReturn("my.authority.for.tray");

from tray.

jannisveerkamp avatar jannisveerkamp commented on May 30, 2024

As @passsy mentioned I guess Robolectric doesn't find a generated String for the authority.

I'm not an Robolectric expert, but you can provide a BuildConfig for it. Make sure you register the correct Provider for Robolectric too. Here is an example (which hopefully works πŸ˜„ )

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class MyAwesomeTest {

    @Before
    public void setUp() throws Exception {
        TrayContentProvider provider = new TrayContentProvider();
        provider.onCreate();
        ShadowContentResolver.registerProvider(BuildConfig.APPLICATION_ID + ".preferences", provider);
    }

    @Test
    public void myTotallyAwesomeTest() throws Exception {
        AppPreferences appPreferences = new AppPreferences(RuntimeEnvironment.application);
        appPreferences.put("key", "test");
        String test = appPreferences.getString("key");
        assertThat(test, equalTo("test"));
    }
}

Let me know if this works. Note that the parameters may vary in your case. This configuration should be valid for the Tray sample project.

from tray.

KioKrofovitch avatar KioKrofovitch commented on May 30, 2024

Thank you both so much for your help! I have now successfully moved on from the URI error, but still get an error during setUp when I attempt to access R.string.tray__authority.

android.content.res.Resources$NotFoundException: unknown resource 2131034186

I also get the same error if I skip the string resource mocking code and I attempt to run only the code suggested by @jannisveerkamp . I get the error when I call provider.onCreate() (which ultimately attempts to access R.string.tray__authority).

Its like Robolectric cannot even see this string resource at all.

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk=21)
public class TrayTest {

  @Before
  public void setUp() throws Exception {
    RuntimeEnvironment.application = spy(RuntimeEnvironment.application);
    when(RuntimeEnvironment.application.getApplicationContext())
        .thenReturn(RuntimeEnvironment.application);

    Resources spiedResources = spy(RuntimeEnvironment.application.getResources());
    when(RuntimeEnvironment.application.getResources())
        .thenReturn(spiedResources);

    when(spiedResources.getString(R.string.tray__authority))
        .thenReturn("com.example.tray");

    TrayContentProvider provider = new TrayContentProvider();
    provider.onCreate();
    ShadowContentResolver.registerProvider(BuildConfig.APPLICATION_ID + ".preferences", provider);
  }

  @Test
  public void myTotallyAwesomeTest() throws Exception {
    assertTrue(true);
    //AppPreferences appPreferences = new AppPreferences(RuntimeEnvironment.application);
    //appPreferences.put("key", "test");
    //String test = appPreferences.getString("key");
    //assertThat(test, equalTo("test"));
  }
}

from tray.

KioKrofovitch avatar KioKrofovitch commented on May 30, 2024

Turns out, Robolectric has a difficult time accessing generated resource values. At first I tried extending RobolectricGradleTestRunner class to add extra directories to the resource path, but this did not work. Ultimately, I had to create a shadow resource like this:

@Implements(Resources.class)
public class CustomShadowResource extends ShadowResources {
  @Override
  public CharSequence getText(int id) throws Resources.NotFoundException {
    if (id == R.string.tray__authority) return "com.example.tray";

    return super.getText(id);
  }
}

Then include this Shadow resource in my TrayTest class like this:
@Config(constants = BuildConfig.class, sdk=21, shadows = CustomShadowResource.class)

While I have resolved the missing string resource issue, the provider registration issue has returned as soon as I attempt to create an AppPreferences object:
java.lang.IllegalStateException: could not access stored data with uri content://com.example.tray/internal_preferences/com.example/version?backup=true. Is the provider registered in the manifest of your application?

from tray.

passsy avatar passsy commented on May 30, 2024

I haven't had the time to look deeper into this. But I suggest to mock the Storage of Tray. Instead of TrayPreference you should work with AbstractTrayPreference and inject a Storage which doesn't require a ContenteProvider. You can use the MockTrayStorage. Of cause this doesn't allow you to test multiprocess stuff.

I note that mocking tray for tests isn't as simple as it should. #futureimprovement

from tray.

nihk avatar nihk commented on May 30, 2024

@KioKrofovitch

@Implements(Resources.class)
public class CustomShadowResource extends ShadowResources {
  @Override
  public CharSequence getText(int id) throws Resources.NotFoundException {
    if (id == R.string.tray__authority) return "com.example.tray";

    return super.getText(id);
  }
}

I just tried this but it yields a compilation error: the class cannot resolve the override because there doesn't appear to be any getText(int) method in ShadowResources. I looked at the robolectric source code and don't see it there either. Am I missing something here? Maybe the API changed?

Edit: OK yes it appears the API changed between 3.0 (the version at the time of your post) and 3.1.

Edit2: I more or less copied the 3.0 implementation and integrated it into the code snippet above - below is working code in 3.8.

@Implements(Resources.class)
public class CustomShadowResources {

    @RealObject 
    private Resources realResources;

    public String getText(@StringRes int id) throws Resources.NotFoundException {
        if (id == R.string.tray__authority) return "com.example.tray";

        CharSequence text = Shadow.directlyOn(realResources, Resources.class).getText(id);
        return StringResources.processStringResources(text.toString());
    }
}

from tray.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.