Espresso testing android - android

I run the tests in Android Studio, running task - "test". My test failed, my html report detailed:
junit.framework.AssertionFailedError: Class Test has no public constructor TestCase(String name) or TestCase()
at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.TestCase.fail(TestCase.java:227)
at junit.framework.TestSuite$1.runTest(TestSuite.java:100)
at junit.framework.TestCase.runBare(TestCase.java:141)
at junit.framework.TestResult$1.protect(TestResult.java:122)
at junit.framework.TestResult.runProtected(TestResult.java:142)
at junit.framework.TestResult.run(TestResult.java:125)
at junit.framework.TestCase.run(TestCase.java:129)
at junit.framework.TestSuite.runTest(TestSuite.java:255)
at junit.framework.TestSuite.run(TestSuite.java:250)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
My source file:
#LargeTest
public class Test extends ActivityInstrumentationTestCase2<MainActivity>{
public Test(Class <MainActivity> activityClass) {
super(activityClass);
}
#Override
public void setUp() throws Exception {
super.setUp();
getActivity();
}
public void testCheck(){
onView(withId(R.id.text))
.check(matches(withText("Hello world!")));
}
}

The problem is exactly what the error message says it is: You did not provide a parameter-free constructor.
Add this constructor to your test class:
public Test() {
super(MainActivity.class);
}

The prototype of a test class with espresso should be:
public class MainTest extends
ActivityInstrumentationTestCase2<MainActivity>{
public MainTest() {
super(MainActivity.class);
}
#Override
public void setUp(){
getActivity();
}
#Override
public void tearDown(){
}
public void test1(){
}
public void test2(){
}
}

Related

Unit testing while using Dagger 2 (Robolectric and Mockito)

I'm trying to write some tests for fragments which have fields annotated with #Inject. For example, a chunk of my app looks like this:
Module:
#Module
public class PdfFactoryModule {
#Provides #Singleton
PdfFactory providePdfFactory() {
return PdfFactory.getPdfFactory();
}
}
Component:
#Singleton
#Component(modules = PdfFactoryModule.class)
public interface CorePdfComponent {
void inject(PagerFragment pagerFragment);
}
Application:
public class CorePdfApplication extends Application {
#NonNull
private CorePdfComponent component;
#Override
public void onCreate() {
super.onCreate();
component = DaggerCorePdfComponent.builder().build();
}
#NonNull
public CorePdfComponent getComponent() {
return component;
}
}
PagerFragment:
public class PagerFragment extends Fragment {
#Inject PdfFactory pdfFactory;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Dagger 2
((CorePdfApplication) getActivity().getApplication()).getComponent().inject(this);
}
(Note that these are only snippets of my whole code, I'm showing only the essentials for this particular dependency to keep it clear.)
I was trying to do a test like this:
Fake Module:
#Module
public class FakePdfFactoryModule extends PdfFactoryModule {
#Override
PdfFactory providePdfFactory() {
return Mockito.mock(PdfFactory.class);
}
}
Fake Component:
#Singleton
#Component(modules = FakePdfFactoryModule.class)
public interface FakeCorePdfComponent extends CorePdfComponent {
void inject(PagerFragmentTest pagerFragmentTest);
}
Fake Application:
public class FakeCorePdfApplication extends CorePdfApplication {
#NonNull
private FakeCorePdfComponent component;
#Override
public void onCreate() {
super.onCreate();
component = DaggerFakeCorePdfComponent.builder().build();
}
#NonNull
public FakeCorePdfComponent getComponent() {
return component;
}
}
Test:
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21, application = FakeCorePdfApplication.class)
public class PagerFragmentTest {
PagerFragment pagerFragment;
#Before
public void setup() {
pagerFragment = new PagerFragment();
startVisibleFragment(pagerFragment);
}
#Test
public void exists() throws Exception {
assertNotNull(pagerFragment);
}
But the DaggerFakeCorePdfComponent doesn't generate. I may have messed up big time because I never tested with dependency injection. What am I doing wrong?
My advice - "Do not use dagger in tests".
Just change your code to next:
public class FakeCorePdfApplication extends CorePdfApplication {
#NonNull
private CorePdfComponent component = mock(CorePdfComponent.class);
#Override
public void onCreate() {
super.onCreate();
}
#NonNull
public CorePdfComponent getComponent() {
return component;
}
}
And:
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21, application = FakeCorePdfApplication.class)
public class PagerFragmentTest {
PagerFragment pagerFragment;
#Before
public void setup() {
pagerFragment = new PagerFragment();
CorePdfComponent component = ((CorePdfApplication)RuntimeEnvironment.application).getComponent();
doAnswer( new Answer() {
Object answer(InvocationOnMock invocation) {
fragment. pdfFactory = mock(PdfFactory.class);
return null;
}
}).when(component).inject(pageFragment);
startVisibleFragment(pagerFragment);
}
#Test
public void exists() throws Exception {
assertNotNull(pagerFragment);
}
}
You may try:
androidTestApt "com.google.dagger:dagger-compiler:<version>"
I was having similar problem, it worked for me.

Testing MVP Android with Retrofit included

I'm developing application based on MVP pattern using retrofit to perform networking. I want to unit test my presenter but it fails.
In my app dataView implements DataView which is mocked by Mockito. In
DataPresenter in onViewCreated method MyApi instance is get from MyApplication and it performs request. Anonymous Subscriber<Data> onNext calls showData(Data data) on dataView. Unfortunatelly Mockito.verify(dataView).showData(data) fails the test. I mocked retrofit client by my self to response in deterministic way.
Code below:
public class DataFragment extends ProgressFragment implements DataView {
protected DataPresenter mDataPresenter;
//[...] initialization arguments boilerplate etc.
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mDataPresenter.onViewCreated(mId);
//[...]
}
#Override
public void startLoading() {
setContentShown(false);
}
#Override
public void stopLoading() {
setContentShown(true);
}
#Override
public void showData(Data data) {
setContentEmpty(false);
//[...] present data
}
#Override
public void showError() {
setContentEmpty(true);
setEmptyText(R.string.unknown_error);
}
}
In DataPresenter:
#Override
public void onViewCreated(long id) {
getView().startLoading();
MyApplication.getInstance().getMyApi().checkIn(User.getUser().getFormattedTokenForRequest(),
(int) id).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(new Subscriber<Data>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
getView().showError();
getView().stopLoading();
}
#Override
public void onNext(Data data) {
getView().showData(data);
getView().stopLoading();
}
});
;
}
My test case:
public static final String GOOD_RESPONSE = "[Data in JSON]"
public static final int GOOD_STATUS = 201;
#Mock
DataView mDataView;
#Mock
MyApplication app;
#Mock
SharedPreferencesManager mSharedPreferencesManager;
DataPresenter mDataPresenter;
#Before
public void setUp() throws Exception {
mDataPresenter = new DataPresenterImpl(mDataView);
MyApplication.setInstance(app);
Mockito.when(app.getSharedPreferencesManager()).thenReturn(mSharedPreferencesManager);
Mockito.when(mSharedPreferencesManager.getUser()).thenReturn(null);
}
#Test
public void testCase() throws Exception {
RestAdapter adapter = (new RestAdapter.Builder()).setEndpoint(URL)
.setClient(new MockClient(GOOD_RESPONSE, GOOD_STATUS))
.build();
Mockito.when(app.getMyApi()).thenReturn(adapter.create(MyApi.class));
mCheckInPresenter.onViewCreated(3);
Mockito.verify(checkInView).startLoading();
Mockito.verify(checkInView).showData(new Data());
}
Test fails on "Wanted but not invoked:
dataView.showData(..." .
What is interesting Response execute() is called in MockClient but onNext(Data data) in subscriber included in DataPresenterImpl is not. Any ideas? I guess it is a problem with request being asynchronous.
The problem is that the work is being sent to a different thread and mockito cant verify whats going on. My solution to this would be to create a scheduler factory and mock it out and return the main thread for tests
like these. Something like:
public class schedulerFactory {
public Scheduler io() {
return Schedulers.io();
}
//etc
}
then in your test you would write something like this:
#Mock SchedulerFactory factory
#Before
public void setUp() {
when(factory.io()).thenReturn(Schedulers.mainThread());
}
in general its a good idea to run all the code in the same thread for testing

It seems that setup() is not called when the test is running

I am developing a test class for my application. The test class code looks like this:
public class ProfileActivityTest extends ActivityInstrumentationTestCase2<ProfileActivity> {
ProfileActivity profileActivity;
#SuppressLint("NewApi")
public ProfileActivityTest(Class<ProfileActivity> activityClass) {
super(activityClass);
// TODO Auto-generated constructor stub
}
#SuppressLint("NewApi")
public ProfileActivityTest() {
super(ProfileActivity.class);
}
protected void setup() throws Exception {
super.setUp();
profileActivity = getActivity();
}
public void test_profileActivityLoggingIn() {
assertNotNull(profileActivity);
assertEquals(View.GONE, profileActivity.findViewById(R.id.btnAddOrEdit).getVisibility());
}
protected void tearDown() throws Exception {
super.tearDown();
}
}
The problem is that I get assertionFailure on assertNotNull(profileActivity) though profileActivity is instantiated in setup(). I don't understand what I am doing wrong;
As #njzk2 has mentioned, "setup" should be changed to "setUp".

Test Fragment with espresso lib

My app has only one activity and based on many fragments. How I can test this fragment in a right way? Give me an example, please.
Cause I try this test class:
#LargeTest
public class ActivityTest extends ActivityInstrumentationTestCase2<ActivityEx> {
public ActivityTest() {
super(ActivityEx.class);
}
public void setUp() throws Exception {
super.setUp();
getActivity();
}
public void testTest() {
//simple example
assertEquals(true, true);
}
}
And in result I've failed due to ClassCastException.
Rather do it like this:
public class ActivityTest extends android.test.ActivityInstrumentationTestCase2
{
public ActivityTest()
{
super(ActivityEx.class);
}
#Override
protected void setUp() throws Exception
{
super.setUp();
getActivity();
}
public void testTest() {
//simple example
assertEquals(true, true);
}
}
If you interested I also posted a tutorial on testing fragments http://www.stevenmarkford.com/testing-fragments-with-android-espresso-basic-example/

Runtime Exception in Android JUnit testing

I have a simple HelloWorld Activity that I try to test with an Android JUnit test. The application itself runs like it should but the test fails with an
"java.lang.RuntimeException: Unable to resolve activity for: Intent { action=android.intent.action.MAIN flags=0x10000000 comp={no.helloworld.HelloWorld/no.helloworld.HelloWorld} }
at no.helloworld.test.HelloWorldTestcase.setUp(HelloWorldTestcase.java:21)"
This is my activity class:
package no.helloworld;
import android.app.Activity; import
android.os.Bundle;
public class HelloWorld extends
Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
} }
And the test:
public class HelloWorldTestcase extends ActivityInstrumentationTestCase2 {
private HelloWorld myActivity;
private TextView mView;
private String resourceString;
public HelloWorldTestcase() {
super("no.helloworld.HelloWorld", HelloWorld.class);
}
#Override
protected void setUp() throws Exception {
super.setUp();
myActivity = this.getActivity();
mView = (TextView) myActivity.findViewById(no.helloworld.R.id.txt1);
resourceString = myActivity
.getString(no.helloworld.R.string.helloworld);
}
public void testPreconditions() {
assertNotNull(mView);
}
public void testText() {
assertEquals(resourceString, (String) mView.getText());
}
protected void tearDown() throws Exception {
super.tearDown();
}
Why does the test fail? The activity is (of course) defined in AndroidManifest.xml and the application runs as it should.
The package in the constructor call should match the instrumentation target in the manifest. It should be "no.helloworld" instead of "no.helloworld.HelloWorld"

Categories

Resources