Has anyone successfully integrated JMockIt Unit tests while Mocking Android objects?
For example
If I do something like
#Test
public void contextTest(#Mocked Context context) {
...
}
Just by having the mocked context, it seems JMockIt causes a class rewrite error.
Would be great if someone has an example snippet showing everything is working fine.
Related
Hello I have the following project structure
--App
|--SDK1
|--SDK2
In app I have some test for check SDK1 and SDK2.
In SDK I have a singleton pattern only to set the context by the application class that is in App.
And the context is set in the SDK1.singleton in the App.Application.onCreate
The problem is that when I try to execute the following code I always get null:
#RunWith(RobolectricTestRunner.class)
public class CallTest {
#Before
public void setUp() throws Exception {}
#Test
public void connectToSocketTest() {
if (BuildConfig.FLAVOR.equals("dev")) {
Context context = SDK1.getInstance().getContext();
assertNotNull(context);
...
Any idea why this happens, and how can solve it?
That's not the recommended way to get app context in Android using robolectric. You can get your activity by using below code...
Activity activity = Robolectric.setupActivity(MyActivity.class);
To get the app context, just call activity.getApplicationContext().
EDIT1: If you're using the latest Robolectric version, use
Robolectric.buildActivity(DashboardActivity.class) instead.
EDIT2: Make sure your SDK1 extends MultiDexApplication". Add this #Config(manifest=Config.NONE, application = App.class, sdk = 17)` to
the top of your test class.
Let me know if it works.
I'm using Robolectric 4.2 to write unit test cases for one of my Android applications. The test case is very simple like below:
#Before
public void setUp() {
landingActivity = Robolectric.setupActivity(LandingActivity.class);
}
#Test
public void shouldNotBeNull() {
assertNotNull(landingActivity);
}
But its taking forever to get completed. Can someone help me out what is happening and is there anything I'm missing.
I'm trying to implement a simple test that uses android.os.Process.myPid (actually I have a large class that uses myPid, but to avoid posting large source I simplified everything down to this):
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class ProcessTest {
#Test
public void testTest() {
assertTrue(true);
}
#Test
public void testPid() {
int pid = android.os.Process.myPid();
//assertTrue(true);
}
}
First test passes ok, but second fails with this error message:
java.lang.UnsatisfiedLinkError: android.os.Process.myPid()I
What's wrong? How to test classes that use android.os.Process?
You can't do that in unit tests. You can't access Android OS packages in unit tests. You can mock them! You want a process id, but there's no OS running (apart from the machine you're developing on).
After a while I found solution for my problem -- instrumentation tests. Well, yes, as Krzysztof Kubicki pointed out, it can't be done in unit tests. But while it's possible to mock things, is difficult in real case. I was able to mock pid for my simple test, but the real thing was AesCbcWithIntegrity by Tozny with all bells and whistles, including things like this:
int bytesRead = (Integer) Class
.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_load_file", String.class, long.class)
.invoke(null, "/dev/urandom", 1024);
This is kinda difficult to mock. So, instead of mocking I created instrumentation test and ran tests on emulator.
And that solved my problem without much effort. Yes, instrumentation tests are slow compared to regular unit testing, but at least it works.
I have Android instrumentation tests with Espresso. Some of my tests must be run on an emulator - due to using LinkedIn's TestButler (https://github.com/linkedin/test-butler) library. This library toggles wifi/gsm for specific test runs, and that is why these tests must be run on an emulator.
My question is - can I annotate any specific tests to run on an emulator, while having the other tests run on a real device?
Thanks
Yes, you can use a #ConditionalIgnore annotation as described in http://www.codeaffine.com/2013/11/18/a-junit-rule-to-conditionally-ignore-tests/.
You will have something like
public class SomeTest {
#Rule
public ConditionalIgnoreRule rule = new ConditionalIgnoreRule();
#Test
#ConditionalIgnore( condition = NotRunningOnEmulator.class )
public void testSomething() {
// ...
}
}
public class NotRunningOnEmulator implements IgnoreCondition {
public boolean isSatisfied() {
return !Build.PRODUCT.startsWith("sdk_google");
}
}
EDIT
For this specific case of detecting a device or emulator you can also use #RequiresDevice.
The most straightforward solution I found is to use JUnit Assume API: http://junit.org/junit4/javadoc/4.12/org/junit/Assume.html
So, inside the test methods that can only be run on an emulator, I put this code:
Assume.assumeTrue("This test must be run in an emulator!", Build.PRODUCT.startsWith("sdk_google"));
This results in the said test being ignored when it isn't run on an emulator, and a handy error msg in the run window:
As you can see, the other two tests passed fine (in the green), and the entire test suite was able to run.
I have an android app that I am unit testing. I have 4 test classes each with multiple test methods. I run them all at the same time from a test suite. I ran into a problem on the emulator where the test would just freeze in the middle of running the tests. I switched to using an actual device and the problem went away.
Fast forward a few weeks and I'm not having the same problem while running tests on my device. I have been on Google for the last couple days trying to find a solution but nothing I have found has helped.
The Issue
When I try to run all the tests the test will freeze eventually. And by freeze I mean the test itself freezes. I saw one solution that it might be the phone or eclipse. I restarted my phone, updated everything in eclipse including eclipse itself. I tried changing views to see if maybe the eclipse view was not refreshing but none of that helped. I also tried using the junit v4 library instead of v3.
If I run the test methods individually they all run and pass. Its only when I run them all from the test suite that they fail.
The Log
I checked the log and this is what I get:
03-13 12:11:04.526: I/TestRunner(23175): started: testCheckShowDialogEnabled(com.package.name.MainActivityTest)
after that there is nothing else in the log.
On The Device
The app is finished and is removed from the screen. It it not reopened again at the beginning of the next test.
The Code
Here is the code that I think might be relevant. If you need any more code just let me know.
public class AllTests extends TestSuite {
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(MainActivityTest.class);
suite.addTestSuite(DatabaseHandlerTest.class);
suite.addTestSuite(ClassOneTest.class);
suite.addTestSuite(AnotherActivityTest.class);
return suite;
}
}
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
public MainActivityTest() {
super("com.package.name", MainActivity.class);
}
#Override
public void setUp() throws Exception {
super.setUp();
mMainActivity = getActivity();
mSolo = new Solo(getInstrumentation(), mMainActivity);
}
#Override
protected void tearDown() throws Exception {
super.tearDown();
mMainActivity = null;
}
// all the test methods
}
All my test classes implement setup() and tearDown() similarly.
Anyone out there know why my tests keep freezing? Any help or suggestions are greatly appreciated.
#smk pointed me in the direction to find a solution to this. I just changed my tearDown() to this:
#Override
protected void tearDown() throws Exception {
mSolo.finishOpenActivities();
super.tearDown();
}
Now it works great!