I'm testing database using ProviderTestCase2 super class. Here is my code snippet:
public class MyProviderTest extends ProviderTestCase2<MyProvider>{
private static MockContentResolver resolver;
private static IsolatedContext context;
public MetaDataProviderTest() {
super(MyProvider.class, Provider.AUTHORITY);
}
#Override
protected void setUp() throws Exception {
try{
super.setUp();
resolver = getMockContentResolver();
} catch(Exception e){
}
}
}
public void testfirst(){
Cursor cursor = resolver.query(ProviderContract.Channels.CHANNEL_URI,null,null,null,null);
....
}
}
When I debug the above code Im getting the passed result. When I run it, I get Null cursor implying there is no such table as channel. Please help in solving this. Where did I go wrong?
There was race condition. Introduced delay in Setup(). It's working fine. But I don't know whether this is the exact solution.
you should write the code :
MockContentResolver.addProvider(authority, yourprovider);
then have a try
Related
I am getting the following exception when trying to mock the static method.
For SettingsUtility, static mocking is already registered in the
current thread To create a new mock, the existing static mock
registration must be deregistered
#Before
fun setUp() {
mockStatic(SettingsUtility::class.java) {
`when` { SettingsUtility.method(app) }.thenReturn { "" }}
}
The returned object's MockedStatic.close() method must be called upon completing the test or the mock will remain active on the current thread.
I am not sure if it is the same as how its done in Java. Hope this Java code snippet helps
private static MockedStatic<SettingsUtility> mockedSettings;
#BeforeAll
public static void init() {
mockedSettings = mockStatic(SettingsUtility.class);
}
#AfterAll
public static void close() {
mockedSettings.close();
}
Try doing this way, you will not get this error. It worked for me.
try(MockedStatic mocked = mockStatic(SettingsUtility.class)) {
mocked.when(SettingsUtility::method).thenReturn("whatever you want");
}
Building on #Sudha 's answer.
in Java you can use #BeforeClass and #AfterClass
private static MockedStatic<SettingsUtility> mockedSettings;
#BeforeClass
public static void init() {
mockedSettings = mockStatic(mockedSettings.class);
}
#AfterClass
public static void close() {
mockedSettings.close();
}
Mockito Inline works differently than the Mockito hence the failure. So what needs to be done is initialise and close the mocks explicitly.
You need to initialise the mockedStatic for your class
private MockedStatic<YourClassWithStaticMethod> mockedStatic;
Then add below code in BeforeEach and AfterEach
#BeforeEach
public void init() {
mockedStatic = mockStatic(YourClassWithStaticMethod.class);
}
#AfterEach
public void cleanup() {
mockedStatic.close();
}
And now you can set the mocked expectations.
mockedStatic.when(YourClassWithStaticMethod::staticMethodToMock).thenReturn(yourReturnedMockedObject);
I tried below and worked for me.
MockedStatic mockedStatic = mockStatic(SettingsUtility.class)
mocked.when(SettingsUtility::method).thenReturn("any thing");
...........
//do all stuf
and at last close the mock
mockedStatic.close();
I do not understand what exactly should I do in order to get a clean and a different db from the one that the app uses.
This is my test class:
public class SQLTest extends ProviderTestCase2{
private static String testDbPrefix = "unitTest_";
public SQLTest (){
super(MyContentProvider.class, MyContract.CONTENT_AUTHORITY);
}
#Override
#Before
public void setUp() throws Exception {
//setContext(InstrumentationRegistry.getTargetContext());
RenamingDelegatingContext context = new RenamingDelegatingContext(InstrumentationRegistry.getTargetContext(), testDbPrefix);
setContext(context);
super.setUp();
}
#Test
public void test1(){
//test logic
}
}
I noticed that it always runs on the db that the app uses, even though I'm using a both ProviderTestCase2 and RenamingDelegatingContext, which are supposed to ensure I'm running with a clean db.
Can anyone explain please what am I missing???
Thanks in advance!
I've tried everything already. The startActivity are not receiving the intent. Here's the code:
public class ColaboradorTeste extends ActivityUnitTestCase<ColaboradorMainActivity> {
private UserDAO userDAO;
private ColaboradorMainActivity activity;
public ColaboradorTeste() {
super(ColaboradorMainActivity.class);
}
#Override
protected void setUp() throws Exception{
super.setUp();
startActivity(new Intent(getInstrumentation().getTargetContext(), ColaboradorMainActivity.class), null, null);
activity = (ColaboradorMainActivity)getActivity().getApplicationContext();
userDAO = new UserDAO(activity);
}
public void testBase() throws Exception{
...
}
}
Here's the error:
java.lang.NullPointerException
at br.fsw.seatafmobile.ColaboradorTeste.setUp(ColaboradorTeste.java:23)
I know the problem is in the startActivity, but I really don't know how to solve it.
If anyone could help I'll really appreciate.
I finally found the solution!
My test is using a database created on the app. So I had to change the Build Variants from Unit Test to Android Instrumentation Tests.
I'm trying to test a ContentProvider class, and can't make it work.
getProvider() keeps returning null, but as I understand from the ProviderTestCase2.setUp() code, it shouldn't.
public class NotesProviderTest extends ProviderTestCase2<NotesProvider>
{
...
public NotesProviderTest()
{
super(NotesProvider.class, Contract.AUTHORITY);
}
#Override
protected void setUp() throws Exception
{
super.setUp();
}
public void testNoteProvider__inserts_a_valid_record() throws Exception
{
Note note = new Note(new JSONObject(simpleNoteJson));
NotesProvider provider = getProvider();
Uri insert = provider.insert(Note.URI, note.getContentValues());
assertEquals(1L, ContentUris.parseId(insert));
Cursor cursor = provider.query(Note.URI, null, null, new String[]{}, null);
assertNotNull(cursor);
cursor.close();
}
}
Side note: the provider works if used within the app.
Thanks in advance.
I just ran into this issue myself. You need to tell AndroidJUnit4 to run the setUp method with the #Before annotation. If you don't do this the setUp method will not be called before your unit test runs.
The code snippet for overriding the setUp method on http://developer.android.com/training/testing/integration-testing/content-provider-testing.html is misleading and doesn't mention that you need an #Before annotation.
Try the following:
#Before
#Override
public void setUp() throws Exception
{
setContext(InstrumentationRegistry.getTargetContext());
super.setUp();
}
As part of the setUp() method a MockContentResolver should be created. Use this to create and inject the provider.
See class MockContentResolver:
http://developer.android.com/reference/android/test/mock/MockContentProvider.html
Source of example:
http://alvinalexander.com/java/jwarehouse/android/test-runner/src/android/test/ProviderTestCase2.java.shtml
Partial sample from example in link above:
#Override
protected void setUp() throws Exception {
super.setUp();
mResolver = new MockContentResolver();
final String filenamePrefix = "test.";
RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(
new MockContext2(), // The context that most methods are delegated to
getContext(), // The context that file methods are delegated to
filenamePrefix);
mProviderContext = new IsolatedContext(mResolver, targetContextWrapper);
mProvider = mProviderClass.newInstance();
mProvider.attachInfo(mProviderContext, null);
assertNotNull(mProvider);
mResolver.addProvider(mProviderAuthority, getProvider());
}
anyone could help me with the problem: how to test android apps which uses ormlite?
I'd like to know how to create mocks form dao. This code gets me a dao
public Dao<Account, Integer> getAccountDao() throws SQLException {
if (accountDao == null) {
accountDao = getDao(Account.class);
}
return accountDao;
}
My testing activity looks this:
public class OrmActivity extends OrmLiteBaseActivity<DatabaseHelper> {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initUi();
initUiListeners();
RuntimeExceptionDao<Account, Integer> accountDao = getHelper().getAccountDataDao();
Account account = new Account();
account.setName("name");
account.setPassword("password");
accountDao.create(account);
}
I dont want to create separate database for tests. Instend of it I want to use mocks.
Best regards
Just in case anyone else stumbles across this post. The issue I had was that you need an instance of an Activity so you can pass the context to the OpenHelperManager.getHelper(android.content.Context context, Class openHelperClass) method.
To get around this I create a ActivityInstrumentationTestCase2 test class to provide the context. You could use MockContext but I understand it to be problematic. This way is simple stupid, sort of :)
At that point I don't bother testing any of the Activity functionality, just database functionality.
public class TestActivity extends ActivityInstrumentationTestCase2<MainFragment> {
public TestActivity() {
super(MainFragment.class);
}
protected void setUp() throws Exception {
super.setUp();
//DatabaseHelper.class is the extended OrmLiteSqliteOpenHelper class
OpenHelperManager.getHelper(getActivity(), DatabaseHelper.class);
}
protected void tearDown() throws Exception {
OpenHelperManager.releaseHelper();
super.tearDown();
}
public void testDetailDiscount() {
//Example code using an entity class that encapsulates ormlite functionality
double total = 95 * 5;
DocumentDetail detail = DocumentDetail.create(getActivity());
assertEquals(total, detail.getTotal());
}
}
Hope it helps
I use Robolectric for unit testing Android apps. Works fine with RoboGuice and Ormlite. Robolectric creates its own database, so a unit test doesn't modify the database on the device you are testing with.
If this doesn't answer your question, please clarify your question. Like, how is not using a separate database related to using mock dao's?