Unit testing a method which is inside an Android Activity - java

I don't know if it has been answered or not, I found some similar questions but the answers are not making any sense to me. So, I am asking it again.
How can we test a method which is inside an activity.
public class MyActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
//inflate layout
}
public int someMethod() {
//perform some logic and return an integer
}
}
I want to unit test the method someMethod but how can I do this as I cannot create an instance of the activity and directly call that method. The method under test does not use any android component so I dont want to use Roboelectric or any other such libraries or tools. It is a plain java method.
One way I know is to move the method to another class and have that class unit tested and I am perfectly fine with it, but I wanted to know if that is the right way, (create a separate class just for this purpose), or is there any other way to do it?
Thank you for any feedback.

To go a bit into theory, you do not want to test a single method in another class.
Following S.O.L.I.D. and D.R.Y. principles, your classes shall have a single responsibility.
So if you think that you want to test only one single method, this method clearly has another responsibility than the rest of the class. Which leads us to: It should not be in that particular class.
Unit Tests are only as good (and as valuable) as the plan behind the testing.
To answer your question: Yes you can call a new myActivitiy() and the unit test might run it (at least I think so). But if the method uses runtime values / context or any other thing from that activity, you can't without running Espresso or similar frameworks.
I recommend to create a proper object model that is testable.
Unit tests can only test code that is written testable
cheers, Gris

Related

Mockito verify that ONLY a expected method was called

I'm working in a Project with a Service class and some sort of a Client that acts as a facade (don't know if it's the right term in the Design Patterns's world, but I'll try to make myself clear). Service's methods can be very expensive as they may be communicating with one or more databases, long checkings and so on, so every Client method should call one and only one Service method.
Service class structure is something like
public class Service {
public void serviceA(){...}
public SomeObject serviceB(){...}
// can grow in the future
}
And Client should be something like
public class Client {
private Service myService; // Injected somehow
public void callServiceA() {
// some preparation
myService.serviceA();
// something else
}
public boolean callServiceB(){...}
}
And in the test class for Client I want to have something like
public class ClientTest{
private Client client; // Injected or instantiated in #Before method
private Service serviceMock = mock(Service.class);
#Test
public void callServiceA_onlyCallsServiceA() {
client.callServiceA();
????
}
}
In the ???? section I want something like verifyOnly(serviceMock).serviceA() saying "verify that serviceMock.serviceA() was called only once and no other method from the Service class was called". Is there something like that in Mockito or in some other mocking library? I don't want to use verify(serviceMock, never()).serviceXXX() for every method because, as I said, Service class may grow in the future and I will have to be adding verification to every test (not a happy task for me) so I need something more general.
Thanks in advance for your answers.
EDIT #1
The difference between this post and the possible duplicate is that the answer adds boiler plate code which is not desired in my case because it's a very big project and I must add as few code as posible.
Also, verifyNoMoreInteractions can be a good option even when it's discouraged for every test, no extra boiler plate code needed.
To sumarize, the possible duplicate didn't solved my problem.
There's another issue: I'm writing test for code made by another team, not following a TDD proccess myself, so my test should be extra defensive, as stated in this article quoted in the mockito documentation for verifyNoMoreInteractions. The methods I'm testing are often very longs so I need to check that the method under test calls ONLY the necesary services and no other (because they're expensive, as I said). Maybe verifyNoMoreInteractions is good enough for now but I'd like to see something not being discouraged for every test by the very same API creator team!
Hope this helps to clarify my point and the problem. Best regards.
verify(serviceMock, times(1)).serviceA();
verifyNoMoreInteractions(serviceMock);
From Mockito's javadoc on verifyNoMoreInteractions:
You can use this method after you verified your mocks - to make sure that nothing else was invoked on your mocks.
Also:
A word of warning: Some users who did a lot of classic, expect-run-verify mocking tend to use verifyNoMoreInteractions() very often, even in every test method. verifyNoMoreInteractions() is not recommended to use in every test method. verifyNoMoreInteractions() is a handy assertion from the interaction testing toolkit. Use it only when it's relevant. Abusing it leads to overspecified, less maintainable tests.
The only way you can reliably verify that your service is only ever called once and only once from the method you specify and not from any other method, is to test every single method and assert that your serviceA method is never invoked. But you're testing every other method anyway, so this shouldn't be that much of a lift...
// In other test cases...
verify(serviceMock, never()).serviceA();
While this is undesirable from a code writing standpoint, it opens the door to separating out your service into smaller, more responsible chunks so that you guarantee that only one specific service is called. From there, your test cases and guarantees around your code become smaller and more ironclad.
I think what you are looking for is the Mockito.verify and Mockito.times
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
verify(mockObject, atLeast(2)).someMethod("was called at least twice");
verify(mockObject, times(3)).someMethod("was called exactly three times");
Here another thread with the same question:
Mockito: How to verify a method was called only once with exact parameters ignoring calls to other methods?

Instance vs static in making a blackbox method in android

My question is regarding in creating a method to be used in my android app. This method is a blackbox that accepts string as a parameter then converts the string object into something.
I want to call this method everytime a certain button is clicked (from a fragment and activity) and I'm wondering if static is the better approach for this since i dont need to instantiate.
I read the answer in Difference between Static methods and Instance methods and says that static is better but i found a blog that one should avoid static as possible.
So what's better approach to implement for my blackbox method?
If you place your method in activity class which contains button with onClickListener calls this method, there is no need to make it static, because the instance of activity created anyway.
If you use a separate class with utils methods, then it may be a good idea to use a static method.
This article is simple explanation of rules to make a method static in Java

Is it bad practice to pass the instance of an Activity as a parameter and finish() it from a different class?

I have a few Activities that use the exact same methods logout() and redirect() multiple times.
Would it be alright to use a separate class and mark these methods as static as follows:
public class AuthUtil {
public static void redirect(SessionManager manager, Activity activity) {
manager.redirect();
activity.finish();
}
public static void logout(SessionManager manager, Activity activity) {
manager.logoutUser();
activity.finish();
}
}
And call them from the activity by:
AuthUtil.logout(mSession,this);
Or should I be extending the Activities that use the method to a common Activity class and just put the methods there (except without the parameters since the methods wouldn't need them in that case)? However, I won't be able to do this if one of the activities extends FragmentActivity, another ActionBarActivity, which is actually the case for me...
Basically, I want to know if it's bad practice to call the activity's methods like that from a separate class body than its own? If so, what should I be doing?
No it is not considered bad practice - but choosing that route because it is easiest may well be a decision you later regret.
You should ask yourself the following questions:
Who is responsible for finishing the activity?.
Who knows when to finish the activity?.
Who knows how to finish the activity? (usually the Activity but be certain).
In your case it could be:
The activity itself
The session manager
The algorithm
Something else entirely
Once you have answered those questions you should have a good idea how to implement.
Remember that you could also create a third object, perhaps an ActivityManager that takes responsibility. It could hold a list of activities that need to be finished when the SessionManagercompletes the session. You may then have:
sessionManager.redirect(activityManager);
other scenarios could result in
// Make sure when the session completes this activity is finished.
sessionManager.registerAttachedActivity(Activity activity);
or
// Activity must finish when redirect completes.
activity.finish(sessionManager.redirect());
It really isn't as simple as good practice and bad practice it's more about doing it right.
Would it be alright to use a separate class and mark these methods as
static as follows
No. It would make very difficult to figure out where are the activities being finished by looking only at the source code of a given activity. And its also hard to see in what thread are those methods running for instance. And finally, because they are static, you'll have to add a new method if an activity needed to perform additional or different actions when redirecting or logging out.
Or should I be extending the Activities...
In my experience it is not a good idea to tie activities to an inheritance hierarchy, and you named a few good reasons for not doing so. If you need code reuse try to use composition instead.
I'd always call Activity.finish from the very same activity, in fact I'd like to have the whole lifecycle picture contained in the activity's code. But this is just what my guts tell me, there's no definitive correct answer to your question.

Android: Verifying behavior using Unit Tests

So let's say I have a simple activity as follows. Assume all of the the lifecycle events etc. are correctly created there's no exception in creating an activity.
public class ButtonClickActivity extends Activity implements OnClickListener {
... onCreate etc. ...
#Override
public void onClick(View v) {
logInfo();
}
protected void logInfo() {
Log log = new Logger();
log.log('foo');
...
}
}
How exactly would you test that the onClickMethod calls on callMyOtherMethod? How also would you test that logInfo makes a new Logger and .log('foo')? Let's assume you have all frameworks at your disposal.
I've tried to use Robolectric (which is fine for high level testing, but really doesn't seem to let you get down into detail like to test if a method calls another method).
It seems that you have to use that in conjunction with a mocking framework / injection in order to verify at least injected object behavior. It doesn't to be able to test 'new Construction' so you're forced to use a factory always for every single object, even for objects you use from other frameworks etc.
I've given a shot with JMockIt (which allows you to verify every single new construction etc.) but it seems there is a problem there also with ByteCode manipulation and it basically will fail if it tries to rewrite bytecode for Android Activities and Views especially, along with other problems.
So my question for folks is what strategy have they been going with other than 'it's a implementation detail' or 'doesn't need to be tested'? I'm sure of course you don't want to test every little detail method call but letting important method calls go unverified doesn't seem like a good solution either.

How to test an anonymous inner class that calls a private method

We have a bunch of classes that listen for events from the server and then respond to them. For example:
class EventManager {
private Set<Event> cache = new HashSet<Event>();
private EventListener eventListener = new EventListener() {
void onEvent(Event e) {
if (e instanceof MyEvent || e instanceof YourEvent) {
handleEvent(e);
}
}
}
public EventManager(ServerCommunication serverComm) {
serverComm.addListener(eventListener);
}
private handleEvent(Event e) {
// handle the event...
// ...
cache.add(cache);
// ...
}
}
Here's a made-up example of the kind of thing we are doing. Here are the problems I see:
I'd like to test handleEvent to make sure it's doing what it is supposed to but I can't because it's private.
I'd also like to check that something got added to the cache too but that also seems difficult since cache is a private member and I don't want to add a needless getter method.
I'd also like to test the code inside the anonymous class's onEvent method.
For now, what I did was move all logic from the anonymous class to the handleEvent method, and I made handleEvent package private (my unit test is in the same package). I'm not checking the contents of the cache although I want to.
Does anyone have any suggestion for a better design that is more testable?
I would probably extract a EventCache component. You can replace this for your test with an implementation that counts the cached events or records whatever is of interest.
I probably would not change the visibility of handleEvent. You could implement a ServerCommunication that just raises the event from the test case.
Well, there are two approaches here: black box and white box.
Black box testing suggests you should only test the publicly visible changes. Does this method have any observable effect? (Some things don't - caches being an obvious example where they improve performance but may otherwise be invisible.) If so, test that. If not, test that it isn't having a negative effect - this may well just be a case of beefing up other tests.
White box testing suggests that maybe you could add a package-level method for the sake of testing, e.g.
Cache getCacheForTesting()
By putting "for testing" in the name, you're making it obvious to everyone that they shouldn't call this from production code. You could use an annotation to indicate the same thing, and perhaps even have some build rules to make sure that nothing from production does call such a method.
This ends up being more brittle - more tied to the implementation - but it does make it easier to test the code thoroughly, IMO. Personally I err on the side of white box testing for unit tests, whereas integration tests should definitely be more black box. Others are rather more dogmatic about only testing the public API.
I assume your EventManager is a singleton, or you have access to the particular instance of the class you're testing.
1 - I suppose you can send events to your class. Your method is private, and nobody else can call it, then sending an event should be enough.
2 - You can access that through reflection, if you really need to. Your test would depend on a particular implementation.
3 - What would you like to test, actually? If you want to be sure that this method is called, you can replace the EventListener with another EventListener object through reflection (and eventually call the onEvent method of the first listener from your new listener). But your question seems to be more about code coverage than actual unit-testing.
Sometimes, when coming across private methods that I want to test... they are simply screaming to be public methods on another object.
If you believe that HandleEvent is worth testing in isolation (and not through onEvent processing), one approach would be to expose HandleEvent as a public method on new/different object.
Use this opportunity to break the code up into smaller more focussed (default access) classes. A test is just another client for the code.
Note that the anonymous inner class' onEvent method is actually accessible, so calling it should not be a problem.

Categories

Resources