The problem
A presenter that "manages" a passive view subscribes to events that occur in that view (e.g. button click), and does not directly expose the methods that handle those events as public interface. I don't like the idea to make those methods public just for unit-testing since it smells like exposing the internal implementation details. Therefore, calling that event handling code becomes quite non-trivial.
My solution
The view mock has to "intercept" the event subscription and then the corresponding intercepted listener is used to call the event handling code. My implementation includes a utility class that implements the Answer interface from the Mockito API
private class ArgumentRetrievingAnswer<TArg> implements Answer {
private TArg _arg;
#Override
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
_arg = (TArg)args[0];
return null;
}
public TArg getArg() {
return _arg;
}
}
The event subscription is intercepted in the following way
XyzView xyzView = mock(XyzView.class);
ArgumentRetrievingAnswer<OnEventListener> xyzViewTouchedListenerInterceptor =
new ArgumentRetrievingAnswer<OnEventListener>();
doAnswer(xyzViewTouchedListenerInterceptor)
.when(xyzView).addViewTouchedListener(any(OnEventListener.class));
After creating the SUT instance...
XyzPresenter sut = new XyzPresenter(xyzView);
...I obtain the listener
OnEventListener xyzViewTouchListener = xyzViewTouchedListenerInterceptor.getArg();
In the "Act" part I call the event handling method of the listener
xyzViewTouchListener.onEvent();
The question
I'm quite new to unit testing in Java, so I'd like to know if there's any more elegant way of testing the presenter code. The current "Arrange" part is quite bloated an does not seem to excel in readability.
Edit:
Adding the simplified SUT code on Jonathan's request. It illustrates that the presenter does not have any public methods (except constructor), and subscribes to the view events.
public interface XyzView {
void setInfoPanelCaptionText(String text);
void addViewInitializedListener(OnEventListener listener);
void addViewTouchedListener(OnEventListener listener);
}
public class XyzPresenter {
private XyzView _xyzView;
private OnEventListener _xyzViewTouchedListener = new OnEventListener() {
#Override
public void onEvent() {
handleXyzViewTouch();
}
};
public XyzPresenter(XyzView xyzView) {
_xyzView = xyzView;
_xyzView.addViewTouchedListener(_xyzViewTouchedListener);
}
private void handleXyzViewTouch() {
// event handling code
}
}
Basically I also use ArgumentCaptor in this setup.
The basic layout of my presenter tests is like this :
#RunWith(MockitoJUnitRunner.class)
public class PresenterTest {
private Presenter sut;
#Mock
private View view;
#Captor
private ArgumentCaptor<ViewTouchedListener> listenerCaptor;
private ViewTouchedListener listener;
#Before
public void setUp() {
sut = new Presenter(view);
verify(view).addViewTouchedListener(listenerCaptor.capture());
listener = listenerCaptor.getValue();
}
// test methods have access to both sut and its registered listener
}
Thanks to #Jonathan for suggesting ArgumentCaptor, I can use it instead of my "re-invented wheel" ArgumentRetrievingAnswer. I managed to stub void methods for event subscribing to use ArgumentCaptor, although it has some after-taste of a hack.
ArgumentCaptor<OnEventListener> xyzViewTouchedListenerCaptor =
ArgumentCaptor.forClass(OnEventListener.class);
doNothing().when(xyzView).addViewTouchedListener(xyzViewTouchedListenerCaptor.capture());
Related
I'm a new one in android dev, so I have an app which contain viewPager with 2 UI fragments and 1 nonUIFragment in which operations are performed (i used "setRetainInstance(true)", it deprecated, but i must use it). In this nonUIFragment i have Handler which accepts messages from operations started with ExecutorServices.
But now my task is test this app with Mockito and i'm totaly confused.
Mentor said "you have to mock the operation that produces the result, is performed in a nonUIFragment, and its result is stored in a collection."
How must look this test, I can't create spy() class NonUIFragment and use real methods because of "Method getMainLooper in android.os.Looper not mocked."
All of my methods are void, they don't returne something, how can i trace this chain.
NonUIFragment.java
private NonUIToActivityInterface nonUIInterface;
private final Map<DefOperandTags, HashMap<DefOperationTags, String>> allResultsMap
= new HashMap<>();
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
//Handler pass result to here
public void passAndSaveResult(DefOperandTags operandTag, DefOperationTags operationTag, String result) {
allResultsMap.get(operandTag)).put(operationTag, result);
}
private final Handler handler = new Handler(Looper.getMainLooper()) {
public void handleMessage(Message msg) {
if (msg.what != null)
passAndSaveResult(defOperandTags, defOperationTag, msg.obj.toString());
};
OneOfOperation.java (add value to the List)
public class AddToStartList extends Operation {
public AddToStartList(List list, DefOperationTags operationTag) {
super(list);
key = operationTag;
}
#Override
public void operation(Object collection) {
((List)collection).add(0, "123");
}
So, how can I implement what my mentor said?
This is going to be tricky, because your Android testing library has no implementations, and static methods are generally more difficult to mock safely and effectively.
Recent versions of Mockito have added the ability to mock static methods without using another library like PowerMock, so the first choice would be something like that. If at all possible, use mockStatic on Looper::getMainLooper to mock.
Another solution is to add some indirection, giving you a testing seam:
public class NonUIFragment extends Fragment {
/** Visible for testing. */
static Looper overrideLooper;
// ...
private final Handler handler = new Handler(
overrideLooper != null ? overrideLooper : Looper.getMainLooper()) {
/* ... */
};
}
Finally, if you find yourself doing this kind of mock a lot, you can consider a library like Robolectric. Using Robolectric you could simulate the looper with a ShadowLooper, which would let you remote-control it, while using Mockito for any classes your team has written. This would prevent you from having to mock a realistic Looper for every test, for instance.
I have an Android app that I'm working on and trying to write unit tests for it. The app is written with the MVP architecture and I am trying to test the Presenter-class.
Simplified method I'm trying to test looks like this:
public void userPressedButton() {
service.loadData(new Callback<Data>{
#Override
onResponse(Data data) {
view.showData(data);
}
});
}
Now I want to verify that when the userPressedButton method is called view.showData(data) is called.
I have tried several approaches but I can't seem to figure out how to test this.
Any ideas?
Edit: to clarify, I want to write a unit test
Interesting case.
What i would do is to:
1) - Create a concrete class for that particular Callback:
public class MyCallback implements Callback<Data>{
private View view;
public MyCallback(View view){
this.view = view;
}
#Override
onResponse(Data data) {
view.showData(data);
}
}
Now for this class you can write a unit test which would check whether the onResponse method calls the showData method of the view field.
2) Having extacted the implementation to a concrete class, from the perspective of the class which contains the userPressedButton method, it really is not essential what happens inside of the Callback class.
It is important that a concrete implementation of that interface has been passed:
public void userPressedButton() {
service.loadData(new MyCallback(view));
}
and finally the test:
#InjectMocks
MyClass myClass;
#Mock
Service service;
#Captor
ArgumentCaptor argCaptor;
#Before
public void init(){
MockitoAnnotations.initMocks(this);
}
#Test
public void shouldUseMyCallback(){
// Arrange
// set up myClass for test
// Act
myClass.userPressedButton();
Mockito.verify(service).loadData(argCaptor.capture());
// Assert
assertTrue(argCaptor.getValue instance of MyCallback);
}
So we check whether the loadData method has been called with proper implementation.
Thats how i would test your case.
You could "store" the callback and use a test callback during your test
class YourClass {
private ??? view;
private Callback<Data> callback;
// for testing purposes
protected YouClass(Callback<Data> callback) {
this.callback = callback;
}
public YouClass() {
this(new Callback<Data>{
#Override
onResponse(Data data) {
view.showData(data);
}
});
}
public void userPressedButton() {
service.loadData(this.callback);
}
}
then use some custom callback for your test
Even more simple solution. If this is MVP, you can pass view instance to presenter class. Then test invocation on Mock.
This is what a test method would look like:
MVPView view = mock(MVPView.class);
Presenter presenter = new Presenter(view)
presenter.userPressedButton();
verify(view, atLeastOnce()).showData(any(Data.class));
If the call is asynchronious, then wait for the result, by modifying the last statement:
verify(view, timetout(5000).atLeastOnce()).showData(any(Data.class));
How do I listen ActivityTestRule's beforeActivityLaunched() method in an android test.
My workaround is creating a custom ActivityTestRule and providing a callback on constructor. Is it a bad practice? Same way is it OK to listen for ActivityTestRule constructor method.
Here is my code:
public class CustomActivityTestRule<A extends Activity> extends ActivityTestRule<A> {
public interface onBeforeListener{
void onBefore(String message);
}
private onBeforeListener listener;
public CustomActivityTestRule(Class<A> activityClass, onBeforeListener listener) {
super(activityClass);
}
#Override
protected void beforeActivityLaunched() {
super.beforeActivityLaunched();
listener.onBefore("before activity launch");
}
}
In android test class, I can do something like:
#Rule public CustomActivityTestRule<MainActivity> mainActivityActivityTestRule = new
CustomActivityTestRule<MainActivity>(MainActivity.class, new CustomActivityTestRule.onBeforeListener() {
#Override
public void onBefore(String message) {
//do something before activity starts
}
});
Same way it is able to do something on junit rule instantiating. Is there any other way to listen for junit test rule instantiating?
You can override beforeActivityLaunched without creation of a new class.
I'm using the following in my tests:
#Rule
public ActivityTestRule<MainActivity> mainActivityActivityTestRule = new ActivityTestRule<MainActivity>(MainActivity.class) {
#Override
protected void beforeActivityLaunched() {
super.beforeActivityLaunched();
}
};
You can configure the test rule so it does not start your activity automatically.
#Rule
public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<MainActivity>(MainActivity.class, false, false);
In you setup method you can prepare all what you need and then launch the activity.
activityTestRule.launchActivity(null);
See also
JavaDoc ActivityTestRule constructor
JavaDoc launchActivity method
I have a simple application and want to make it testable. I m new in this area.
Here is a simple Presenter, taking in mind this code ,could you advice or give me some example how to test it.
public class SomePresenter extends Presenter<MainPanelPresenter.Display>
{
public interface Display extends WidgetDisplay
{
HasClickHandlers getAddButton();
HasClickHandlers getDeleteButton();
void setData(ArrayList<Person> data);
ArrayList<String> getSelectedRows();
Widget asWidget();
}
private final DispatchAsync dispatcher;
public static final Place PLACE = new Place("main");
#Inject
public SomePresenter(DispatchAsync dispatcher, EventBus eventBus, Display display)
{
super(display, eventBus);
this.dispatcher = dispatcher;
bind();
}
protected void onBind()
{
display.getAddButton().addClickHandler(new ClickHandler()
{
public void onClick(ClickEvent event)
{
eventBus.fireEvent(new AddButtonEvent());
}
});
display.getDeleteButton().addClickHandler(new ClickHandler()
{
public void onClick(ClickEvent event)
{
ArrayList<String> list = display.getSelectedRows();
deletePerson(list);
}
});
}
....
private void loadDbData()
{
..........
}
private void deletePerson(ArrayList<String> ids)
{
..........
}
}
Edit:
What does the Presenter is, load initial data from db, have 2 buttons add and delete.
When add is press then a new form is load and user is able to input data and save to the db,
delete button just delete person from db.
Thanks
The general idea of unit testing such a class would be, like for any other class :
create Mock version of the dependencies (Display, EventBus, etc...)
set expectations on what the depdencies should do when the Presenter works
exercice the Presenter and check the expectations
However there are a couple of issues with your version of the Presenter :
The loadDbData() method is not showed, but I assumed it means the Presenter also has access to some other component that does the fetching. Can this component be abtracted in a dependency, and mocked liked the rest ?
Then there is the testing of bind(). The only responsibility of your Presenter in this method is to set up callbacks on some buttons provided by the Display. What you want to test is both :
That the callbacks are set
That the set callbacks do the expected things
A few ideas to help with the later :
You can reduce the coupling between Presenter and Button. If possible, change the Display interface from :
Button getAddButton();
to
addAddButtonClickedHandler(ClickHandler);
This means your Presenter does not have to use a Display object that returns actual BUtton
You can reduce the callbacks content to calling a single method, that you can then test in isolation
protected void bind() {
display.addAddButtonClickHandler(new ClickHandler() {
public void onClick(ClickEvent) {
fireAdded();
}
});
}
// The fireAdded function can be tested independenty of the Display, potentially with
// a mock EventBus
protected void fireAdded() {
event.fireEvent(....)
}
If you really want to check that the callbacks are properly set, than you can use a 'Dummy' implementation of the Display class, that provides you a list of all the callbacks, and let you call them
private class DummyDisplay implements Display {
private List<ClickHandler> addButtonClickHandlers;
public void addAddButtonClickHandler(ClickHandler handler) {
addButtonClickHandlers.add(handler);
}
public void fireAddButtonClick() {
for (ClickHandler h in addButtonClickHandlers) {
h.onClick(new ClickEvent());
}
}
// ....
}
Then your test would :
create a presenter with such a dummy display
use bind to set the callbacks
use display.fireAddButtonClick() to simulate a user clicking
check that has the result of the click, the effects of fireAdded are seen
This type of class (that mostly glue other classes together) can tend to be hard to test ; at some point, it the other classes are thoroughly tested it can become slightly counter productive to concentrate on the gluers, rather than the glued.
Hoping this helps.
Very typically I have a situation where a given object will need to have many listeners. For instance, I might have
class Elephant {
public void addListener( ElephantListener listener ) { ... }
}
but I'll have many such situations. That is, I'll also have a Tiger object that'll have TigerListeners. Now, TigerListeners and ElephantListeners are quite different:
interface TigerListener {
void listenForGrowl( Growl qrowl );
void listenForMeow( Meow meow );
}
while
interface ElephantListener {
void listenForStomp( String location, double intensity );
}
I find that I always have to keep re-implementing the broadcasting mechanism in each animal class, and the implementation is always the same. Is there a preferred pattern?
Instead of each Listener having specific methods for every event type you can send it, change the interface to accept a generic Event class. You can then subclass Event to specific subtypes if you need, or have it contain state such as double intensity.
TigerListener and ElephentListener then become
interface TigerListener {
void listen(Event event);
}
In fact, you can then further refactor this interface into a plain Listener:
interface Listener {
void listen(Event event);
}
Your Listener implementations can then contain the logic that they need for the specific events they care about
class TigerListener implements Listener {
#Overrides
void listen(Event event) {
if (event instanceof GrowlEvent) {
//handle growl...
}
else if (event instance of MeowEvent) {
//handle meow
}
//we don't care about any other types of Events
}
}
class ElephentListener {
#Overrides
void listen(Event event) {
if (event instanceof StompEvent) {
StompEvent stomp = (StompEvent) event;
if ("north".equals(stomp.getLocation()) && stomp.getDistance() > 10) {
...
}
}
}
}
The key relationship between the subscriber and the publisher is that the publisher can send events to the subscribers, it isn't necessarily that it can send it certain types of events - this type of refactoring pushes that logic from the interface down into the specific implementations.
This is a more general answer for people who come here just wanting to make a listener. I am summarizing Creating Custom Listeners from CodePath. Read that article if you need more explanation.
Here are the steps.
1. Define an Interface
This is in the child class that needs to communicate with some unknown parent.
public class MyClass {
// interface
public interface MyClassListener {
// add whatever methods you need here
public void onSomeEvent(String title);
}
}
2. Create a Listener Setter
Add a private listener member variable and a public setter method to the child class.
public class MyClass {
// add a private listener variable
private MyClassListener mListener = null;
// provide a way for another class to set the listener
public void setMyClassListener(MyClassListener listener) {
this.mListener = listener;
}
// interface from Step 1
public interface MyClassListener {
public void onSomeEvent(String title);
}
}
3. Trigger Listener Events
The child object can now call methods on the listener interface. Be sure to check for null because there might not be anyone listening. (That is, the parent class might not have called the setter method for our listener.)
public class MyClass {
public void someMethod() {
// ...
// use the listener in your code to fire some event
if (mListener != null)
mListener.onSomeEvent("hello");
}
// items from Steps 1 and 2
private MyClassListener mListener = null;
public void setMyClassListener(MyClassListener listener) {
this.mListener = listener;
}
public interface MyClassListener {
public void onSomeEvent(String myString);
}
}
4. Implement the Listener Callbacks in the Parent
The parent can now use the listener that we set up in the child class.
Example 1
public class MyParentClass {
private void someMethod() {
MyClass object = new MyClass();
object.setMyClassListener(new MyClass.MyClassListener() {
#Override
public void onSomeEvent(String myString) {
// handle event
}
});
}
}
Example 2
public class MyParentClass implements MyClass.MyClassListener {
public MyParentClass() {
MyClass object = new MyClass();
object.setMyClassListener(this);
}
#Override
public void onSomeEvent(String myString) {
// handle event
}
}
I think you're doing it correct, since your interfaces have semantic value and express what they are listening to (e.g. growls and meows instead of stomps). With a generic approach, you may be able to reuse the broadcasting code, but you may lose the readability.
For example, there is the java.beans.PropertyChangeSupport which is a utility for implementing Oberservers listening for value changes. It does the broadcasting, but you still need to implement the method in your domain class and delegate to the PropertyChangeSupport object. The callback methods are meaningless by themselves, and the events broadcasted are String-based:
public interface PropertyChangeListener extends java.util.EventListener {
void propertyChange(PropertyChangeEvent evt);
}
Another one is java.util.Observable which provides the broadcasting mechanism, but it's also not the best thing imho.
I like ElephantListener.onStomp()
A different options is the Whiteboard Pattern. This disconnects the publisher and subscriber from each other, and neither will contain any broadcasting code. They both simply use a messaging mechanism for pub/sub and neither has any direct connection to the other.
This is a common model for messaging in an OSGi platform.
I created a Signals library just for this purpose. To remove the boiler code involved in "re-implementing the broadcasting mechanism."
A Signal is an object created automatically from an interface. It has methods for adding listeners and dispatching/broadcasting events.
It looks like this:
interface Chat{
void onNewMessage(String s);
}
class Foo{
Signal<Chat> chatSignal = Signals.signal(Chat.class);
void bar(){
chatSignal.addListener( s-> Log.d("chat", s) ); // logs all the messaged to Logcat
}
}
class Foo2{
Signal<Chat> chatSignal = Signals.signal(Chat.class);
void bar2(){
chatSignal.dispatcher.onNewMessage("Hello from Foo2"); // dispatches "Hello from Foo2" message to all the listeners
}
}
In this example, Foo2 is the broadcaster of new messages over the Chat interface. Foo then listen to those and log it to logcat.
Note that there are no limitations on what interfaces you can use
You also have some sugar API for registering for only the first broadcast and unregistering from all the signals at once(Via the SignalsHelper)
Try the java kiss library and you will get this done faster and more correctly.
import static kiss.API.*;
class Elephant {
void onReceiveStomp(Stomp stomp) { ... }
}
class Tiger {
void onReceiveMeow(Meow meow) { ... }
void onReceiveGrowl(Growl growl) { ... }
}
class TigerMeowGenerator extends Generator<Meow> {
// to add listeners, you get:
// addListener(Object tiger); // anything with onReceiveMeow(Meow m);
// addListener(meow->actions()); // any lambda
// to send meow's to all listeners, use
// send(meow)
}
The generator is thread-safe and efficient (writing correct generators is the hardest part). It is an implementation of the ideas in
Java Dev. Journal - Skilled Listening in Java (local copy)