public class Feed {
    private String title;
    private String body;
    private String image;
    private String key;
    private int index;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
} public class Written {
} public interface PostExecutionThread {
  Scheduler getScheduler();
} public interface ThreadExecutor extends Executor {} public class NewFeedUseCase extends UseCase {

    @NonNull
    FeedRepository repository;

    @NonNull
    Feed feed;

    @Inject
    public NewFeedUseCase(Feed feed, FeedRepository repository, ThreadExecutor threadExecutor, PostExecutionThread postExecutionThread) {
        super(threadExecutor, postExecutionThread);
        this.repository = repository;
        this.feed = feed;
    }

    @Override
    protected Observable buildUseCaseObservable() {
        return repository.writeFeed(feed);
    }
} public class NewFeedUseCaseFactory {
    private FeedRepository mRepository;
    private ThreadExecutor mThreadExecutor;
    private PostExecutionThread mPostExecutionThread;


    @Inject
    public NewFeedUseCaseFactory(FeedRepository mRepository, ThreadExecutor mThreadExecutor, PostExecutionThread mPostExecutionThread) {
        this.mRepository = mRepository;
        this.mThreadExecutor = mThreadExecutor;
        this.mPostExecutionThread = mPostExecutionThread;
    }

    public NewFeedUseCase create(Feed feed){
        return new NewFeedUseCase(feed, mRepository, mThreadExecutor, mPostExecutionThread);
    }
} public interface FeedRepository {

    public Observable<FeedChangedInfo> registerFeedChangedEvent();

    public Observable<Written> writeFeed(Feed feed);

    public Observable<Deleted> deleteFeed(String key);

} @Singleton
public class FeedModelMapper {


    @Inject
    public FeedModelMapper(){

    }

    public FeedModel transform(Feed entity){
        FeedModel feed = new FeedModel();

        feed.setImage(entity.getImage());
        feed.setBody(entity.getBody());
        feed.setTitle(entity.getTitle());
        feed.setIndex(entity.getIndex());

        return feed;
    }


    public FeedChangedInfoModel transform(FeedChangedInfo entity){
        FeedChangedInfoModel result = new FeedChangedInfoModel();
        result.setKey(entity.getKey());
        result.setPreviousChildKey(entity.getPreviousChildKey());
        result.setFeed(this.transform(entity.getFeed()));

        switch (entity.getType()){
            case Added:
                result.setType(FeedChangedInfoModel.EventType.Added);
                break;
            case Changed:
                result.setType(FeedChangedInfoModel.EventType.Changed);
                break;
            case Moved:
                result.setType(FeedChangedInfoModel.EventType.Moved);
                break;

            case Removed:
                result.setType(FeedChangedInfoModel.EventType.Removed);
                break;
        }

        return result;
    }

    public WrittenModel transform(Written entity){
        WrittenModel result = new WrittenModel();
        // maybe add data later
        return result;
    }

    public DeletedModel transform(Deleted entity){
        DeletedModel result = new DeletedModel();
        // maybe add data later
        return result;
    }

} public final class CompositeUseCases {

    private Set<UseCase> subscriptions;
    private volatile boolean unsubscribed;

    public CompositeUseCases() {
    }



    public void add(final UseCase s) {
        if (s.isUnsubscribed()) {
            return;
        }
        if (!unsubscribed) {
            synchronized (this) {
                if (!unsubscribed) {
                    if (subscriptions == null) {
                        subscriptions = new HashSet<UseCase>(5);
                    }
                    subscriptions.add(s);
                    return;
                }
            }
        }
        // call after leaving the synchronized block so we're not holding a lock while executing this
        s.unsubscribe();
    }


    public void remove(final Subscription s) {
        if (!unsubscribed) {
            boolean unsubscribe = false;
            synchronized (this) {
                if (unsubscribed || subscriptions == null) {
                    return;
                }
                unsubscribe = subscriptions.remove(s);
            }
            if (unsubscribe) {
                // if we removed successfully we then need to call unsubscribe on it (outside of the lock)
                s.unsubscribe();
            }
        }
    }


    public void clear() {
        if (!unsubscribed) {
            Collection<UseCase> unsubscribe = null;
            synchronized (this) {
                if (unsubscribed || subscriptions == null) {
                    return;
                } else {
                    unsubscribe = subscriptions;
                    subscriptions = null;
                }
            }
            unsubscribeFromAll(unsubscribe);

        }
    }



    private static void unsubscribeFromAll(Collection<UseCase> subscriptions) {
        if (subscriptions == null) {
            return;
        }
        List<Throwable> es = null;
        for (UseCase s : subscriptions) {
            try {
                s.unsubscribe();
            } catch (Throwable e) {
                if (es == null) {
                    es = new ArrayList<Throwable>();
                }
                es.add(e);
            }
        }

        Exceptions.throwIfAny(es);
    }


    public boolean hasSubscriptions() {
        if (!unsubscribed) {
            synchronized (this) {
                return !unsubscribed && subscriptions != null && !subscriptions.isEmpty();
            }
        }
        return false;
    }
} public interface NewFeedView {
    public void close();
    public void showErrorMsg();
}
import com.mike.feed.domain.Feed;
import com.mike.feed.domain.Written;
import com.mike.feed.domain.executor.PostExecutionThread;
import com.mike.feed.domain.executor.ThreadExecutor;
import com.mike.feed.domain.interactor.NewFeedUseCase;
import com.mike.feed.domain.interactor.NewFeedUseCaseFactory;
import com.mike.feed.domain.repository.FeedRepository;
import com.mike.feed.mapper.FeedModelMapper;
import com.mike.feed.util.CompositeUseCases;
import com.mike.feed.view.NewFeedView;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import rx.Observable;
import rx.Subscriber;
package com.mike.feed.presenter;





/**
 * Created by MinhNguyen on 8/27/16.
 */
public class NewFeedPresenterTest {

    @Mock
    private NewFeedUseCaseFactory mNewFeedUseCaseFactory;

    @Mock
    private NewFeedUseCase mUseCase;

    @Mock
    private FeedModelMapper mMapper;

    @Mock
    private NewFeedView mView;


    private NewFeedPresenter mPresenter;

    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
        mPresenter = new NewFeedPresenter(mNewFeedUseCaseFactory, mMapper);
        mPresenter.useCasesToUnsubscribeOnUnbindView = Mockito.mock(CompositeUseCases.class);
        mPresenter.bindView(mView);
    }

    @Test
    public void newFeedScreenShouldCloseIfAddNewSuccessful(){
        Observable observable = Observable.create(new Observable.OnSubscribe<Written>() {