Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to test a method in an Activity class?

Everybody recommended to follow MVP or MVVM pattern to maintain code readability and testability. Now I am having doubts. Now I am learning unit testing and I'm writing the code in a formal way. Not using any patterns. Now my question, can I test my code like the following?

My main activity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 
    }

    public boolean testMethod(int value){
       return value== 5?true:false;
    }
}

My unit test class:

@RunWith(MockitoJUnitRunner.class)
public class ExampleUnitTest {
 MainActivity mainActivity = new MainActivity();
@Test
    public void testMethod(){
        boolean result = mainActivity.testMethod(5);
        assertEquals(true,result);
    }
}

While running the test I did not receive any errors or issues. So is this the right way to test like this? Or what will happen if I follow this method? I am also starting to migrate my code to the MVP pattern, but I want to clear my doubts. Please let me know the reason why I should not follow the formal coding for unit testing.

like image 756
Vijayadhas Chandrasekaran Avatar asked Oct 31 '18 06:10

Vijayadhas Chandrasekaran


People also ask

What is activity test rule?

This rule provides functional testing of a single Activity .

Can we unit test private methods?

Why We Shouldn't Test Private Methods. As a rule, the unit tests we write should only check our public methods contracts. Private methods are implementation details that the callers of our public methods aren't aware of. Furthermore, changing our implementation details shouldn't lead us to change our tests.

Can we test private methods in JUnit?

So whether you are using JUnit or SuiteRunner, you have the same four basic approaches to testing private methods: Don't test private methods. Give the methods package access. Use a nested test class.


1 Answers

Your simple example works because the code under test is not actually dependent on the Activity class or any UI state. Try to write a test for code that actually depends on UI state, e.g.

public boolean verifyInput() {
    EditText edit = findViewById(R.id.edit1);
    return edit.getText().toString().startsWith("0");
}

If you keep going down this road you will notice the following things to happen:

  • Your Activity class will become bigger and bigger (god object anti pattern).
  • Code that actually depends on UI state (your example does not) cannot be written with a simple unit test, an Android instrumentation test will be needed. I.e. tests will not be able execute on your host machine anymore, but have to be executed on device and need to set up and bring the Activity in the right state.
  • Instrumentation tests are usually slower and can be flaky, due to the nature of all the heavy lifting that will be needed to handle the UI actions and state. You will receive false negatives in your test runs.
  • Test methods will become more complex, because they have to bring the UI into the correct state to test the logic.

Now, there's a simple solution to all of this. Separate the core logic from the UI logic. Make the code that handles the UI as simple as possible and move the (complex) core logic into a separate class. Suddenly you have a 2nd class with methods that will make it easier for you to reason about and write tests for. This 2nd class will also match the actions the user of your app will be able to take.

After some time you will want to split up the 2nd class too, because you will notice that some subset of methods have nothing to do with another subset of methods. So you keep modularizing and crafting to make it easier for you as a developer to understand and to work with the code. This is the time where patterns like MVP, MVVM, ... will become handy.

Please note that I'm not recommending you to jump into using patterns like MVVM immediately. If you are just starting to learn Programming, Software Development or Android, it is totally fine to do what you do. You'll learn by experiencing these "pain points", that a lot of us have already run into, and at that time you will start to look for improvements and why others recommend to use specific patterns or best practices.

Also, take a look at what low coupling and high cohesion means and why it's important for you as a developer.

like image 147
Maik Avatar answered Oct 12 '22 02:10

Maik