Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

static use of Android classes fails with ParameterizedRobolectricTestRunner #3805

Closed
m-sasha opened this issue Mar 7, 2018 · 7 comments
Closed

Comments

@m-sasha
Copy link

m-sasha commented Mar 7, 2018

Description

I want to write a parameterized test whose data includes Android classes (android.location.Location), specifically. It appears, though, that ParameterizedRobolectricTestRunner installs the classloader too late, because if I create the test data objects in public static Collection<Object[]> data(), I get an exception saying the relevant method was not mocked (meaning the class loaded wasn't Robolectric's).

The same thing (creating a Location in a static block) succeeds with RobolectricTestRunner.

Test source code

@RunWith(ParameterizedRobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class ParameterizedTestTest{


	@ParameterizedRobolectricTestRunner.Parameters
	public static Collection<Object[]> data(){
		Location location = new Location("test");
		location.setTime(System.currentTimeMillis());
		return Arrays.asList(new Object[][]{
			{location}
		});
	}


	private final Location location;


	public ParameterizedTestTest(Location l){
		this.location = l;
	}


	@Test
	public void test(){

	}


}

Robolectric & Android Version

3.6.1 & 23

@SpaceBison
Copy link

This is still present in 4.2:

@RunWith(ParameterizedRobolectricTestRunner.class)
public class RobolectricParametrized {

    @ParameterizedRobolectricTestRunner.Parameters()
    public static Collection<Object[]> getParameters() {
        return Collections.singletonList(new Object[] { Looper.getMainLooper() });
    }

    @ParameterizedRobolectricTestRunner.Parameter
    public Looper looper;

    @Test
    public void test() {
        Assert.assertTrue(looper.isCurrentThread());
    }
}

.

java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.

        at android.os.Looper.getMainLooper(Looper.java)
        at RobolectricParametrized.getParameters(RobolectricParametrized.java:16)

@brettchabot
Copy link
Contributor

Can you post a sample code showing how the same code works with RobolectricTestRunner?

IIUC, this issue is unfortunately expected in Robolectric. The sandboxed classloader is set up before each test method, so accessing any Android classes statically before a test runs is not going to work.

@ggabdol
Copy link

ggabdol commented Jun 19, 2019

Is there any plan to support this feature?

@song-water
Copy link

Hi, is there any actual progress on this issue?

This is still present in 4.6.1.

https://github.com/robolectric/robolectric/blob/master/robolectric/src/test/java/org/robolectric/ParameterizedRobolectricTestRunnerClassLoaderTest.java
is work well in my PC, but fail with Kotlin :

@RunWith(ParameterizedRobolectricTestRunner::class)
  class ParameterizedRobolectricTestRunnerDemoTest(
      private var uri: Uri
  ) {
      @Test
      @Config(manifest = Config.NONE)
      fun parse() {
          val currentUri = Uri.parse("http://host/")
          assertThat(currentUri).isEqualTo(uri)
      }
  
      companion object {
          @ParameterizedRobolectricTestRunner.Parameters
          @JvmStatic
          fun getTestData(): Collection<*> {
              val data = arrayOf(arrayOf<Any>(Uri.parse("http://host/")))
              return listOf(data)
          }
      }
  }

error log:

parse("http://host/") must not be null
java.lang.NullPointerException: parse("http://host/") must not be null

Test environment

Robolectric: 4.6.1
Kotlin: 1.5.31
AGP: 7.0.0
JDK: 11
PC: windows 10

@utzcoz
Copy link
Member

utzcoz commented Apr 8, 2023

@song-water You need to change the type of data in your getTestData method. See #8122 for potential solution.

@utzcoz
Copy link
Member

utzcoz commented Apr 8, 2023

@SpaceBison I tested your occasion with latest Robolectric, and I can get proper main looper value with Parameter. Please try the latest Robolectric to test it again. @m-sasha I think your occasion is similar to @SpaceBison one. Feel free to reopen this issue if this still exists at your part with latest Robolectric.

@utzcoz utzcoz closed this as completed Apr 8, 2023
@jmartinesp
Copy link

@SpaceBison I tested your occasion with latest Robolectric, and I can get proper main looper value with Parameter. Please try the latest Robolectric to test it again. @m-sasha I think your occasion is similar to @SpaceBison one. Feel free to reopen this issue if this still exists at your part with latest Robolectric.

I was trying to get parameterized tests working with robolectric in our project and I saw it fail when using Uris, which seemed quite weird to me, so I also tried adding the test you added above to our project and saw it fail too.

In my case, I can reproduce this with the latest Robolectric version (4.11.1) and using that same test (here is a reproducible project).

I also tried playing with testOptions.unitTests.isReturnDefaultValues and testOptions.unitTests.isIncludeAndroidResources but none seemed to fix the issue. Am I missing something needed for this to actually work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants