51a24fd1c3b00649b9e193d97450e77b77ef8a68
[Sone.git] / src / test / java / net / pterodactylus / sone / data / Mocks.java
1 /*
2  * Sone - Mocks.java - Copyright © 2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.data;
19
20 import static com.google.common.base.Optional.absent;
21 import static com.google.common.base.Optional.fromNullable;
22 import static com.google.common.base.Optional.of;
23 import static com.google.common.collect.ArrayListMultimap.create;
24 import static com.google.common.collect.Ordering.from;
25 import static com.google.common.collect.Sets.newHashSet;
26 import static java.util.Collections.emptySet;
27 import static org.mockito.Matchers.anyString;
28 import static org.mockito.Matchers.eq;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.when;
31
32 import java.util.Collection;
33 import java.util.List;
34
35 import net.pterodactylus.sone.core.Core;
36 import net.pterodactylus.sone.data.impl.DefaultPostBuilder;
37 import net.pterodactylus.sone.data.impl.DefaultPostReplyBuilder;
38 import net.pterodactylus.sone.database.Database;
39 import net.pterodactylus.sone.database.PostReplyBuilder;
40
41 import com.google.common.base.Optional;
42 import com.google.common.collect.FluentIterable;
43 import com.google.common.collect.Multimap;
44 import com.google.common.collect.Ordering;
45 import org.mockito.invocation.InvocationOnMock;
46 import org.mockito.stubbing.Answer;
47
48 /**
49  * Mocks reusable in multiple tests.
50  *
51  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
52  */
53 public class Mocks {
54
55         private final Multimap<Sone, Post> sonePosts = create();
56         private final Collection<Sone> sones = newHashSet();
57         private final Multimap<Post, PostReply> postReplies = create();
58         private final Multimap<String, Post> directedPosts = create();
59         public final Database database;
60         public final Core core;
61
62         public Mocks() {
63                 database = mockDatabase();
64                 core = mockCore(database);
65                 when(core.getLocalSones()).then(new Answer<Collection<Sone>>() {
66                         @Override
67                         public Collection<Sone> answer(InvocationOnMock invocation) throws Throwable {
68                                 return FluentIterable.from(sones).filter(Sone.LOCAL_SONE_FILTER).toList();
69                         }
70                 });
71                 when(database.getDirectedPosts(anyString())).then(new Answer<Collection<Post>>() {
72                         @Override
73                         public Collection<Post> answer(InvocationOnMock invocation) throws Throwable {
74                                 return directedPosts.get((String) invocation.getArguments()[0]);
75                         }
76                 });
77         }
78
79         private static Core mockCore(Database database) {
80                 Core core = mock(Core.class);
81                 when(core.getDatabase()).thenReturn(database);
82                 when(core.getSone(anyString())).thenReturn(Optional.<Sone>absent());
83                 return core;
84         }
85
86         private static Database mockDatabase() {
87                 Database database = mock(Database.class);
88                 when(database.getSone(anyString())).thenReturn(Optional.<Sone>absent());
89                 when(database.getPost(anyString())).thenReturn(Optional.<Post>absent());
90                 when(database.getPostReply(anyString())).thenReturn(Optional.<PostReply>absent());
91                 return database;
92         }
93
94         public SoneMocker mockSone(String id) {
95                 return new SoneMocker(id);
96         }
97
98         public PostMocker mockPost(Sone sone, String postId) {
99                 return new PostMocker(postId, sone);
100         }
101
102         public PostReplyMocker mockPostReply(Sone sone, String replyId) {
103                 return new PostReplyMocker(replyId, sone);
104         }
105
106         public class SoneMocker {
107
108                 private final Sone mockedSone = mock(Sone.class);
109                 private final String id;
110                 private boolean local;
111                 private Optional<String> name = absent();
112                 private long time;
113                 private Profile profile = new Profile(mockedSone);
114                 private Collection<String> friends = emptySet();
115
116                 private SoneMocker(String id) {
117                         this.id = id;
118                 }
119
120                 public SoneMocker local() {
121                         local = true;
122                         return this;
123                 }
124
125                 public SoneMocker withName(String name) {
126                         this.name = fromNullable(name);
127                         return this;
128                 }
129
130                 public SoneMocker withTime(long time) {
131                         this.time = time;
132                         return this;
133                 }
134
135                 public SoneMocker withProfileName(String firstName, String middleName, String lastName) {
136                         profile.modify().setFirstName(firstName).setMiddleName(middleName).setLastName(lastName).update();
137                         return this;
138                 }
139
140                 public SoneMocker addProfileField(String fieldName, String fieldValue) {
141                         profile.setField(profile.addField(fieldName), fieldValue);
142                         return this;
143                 }
144
145                 public SoneMocker withFriends(Collection<String> friends) {
146                         this.friends = friends;
147                         return this;
148                 }
149
150                 public Sone create() {
151                         when(mockedSone.getId()).thenReturn(id);
152                         when(mockedSone.isLocal()).thenReturn(local);
153                         if (name.isPresent()) {
154                                 when(mockedSone.getName()).thenReturn(name.get());
155                         }
156                         when(mockedSone.getTime()).thenReturn(time);
157                         when(mockedSone.getProfile()).thenReturn(profile);
158                         if (local) {
159                                 when(mockedSone.newPostBuilder()).thenReturn(new DefaultPostBuilder(database, id));
160                                 when(mockedSone.newPostReplyBuilder(anyString())).then(new Answer<PostReplyBuilder>() {
161                                         @Override
162                                         public PostReplyBuilder answer(InvocationOnMock invocation) throws Throwable {
163                                                 return new DefaultPostReplyBuilder(database, id, (String) invocation.getArguments()[0]);
164                                         }
165                                 });
166                                 when(mockedSone.hasFriend(anyString())).thenReturn(false);
167                                 when(mockedSone.getFriends()).thenReturn(friends);
168                                 when(mockedSone.hasFriend(anyString())).then(new Answer<Boolean>() {
169                                         @Override
170                                         public Boolean answer(InvocationOnMock invocation) throws Throwable {
171                                                 return friends.contains(invocation.getArguments()[0]);
172                                         }
173                                 });
174                         } else {
175                                 when(mockedSone.newPostBuilder()).thenThrow(IllegalStateException.class);
176                                 when(mockedSone.newPostReplyBuilder(anyString())).thenThrow(IllegalStateException.class);
177                         }
178                         when(core.getSone(eq(id))).thenReturn(of(mockedSone));
179                         when(database.getSone(eq(id))).thenReturn(of(mockedSone));
180                         when(mockedSone.getPosts()).then(new Answer<List<Post>>() {
181                                 @Override
182                                 public List<Post> answer(InvocationOnMock invocationOnMock) throws Throwable {
183                                         return from(Post.TIME_COMPARATOR).sortedCopy(sonePosts.get(mockedSone));
184                                 }
185                         });
186                         when(mockedSone.toString()).thenReturn(String.format("Sone[%s]", id));
187                         sones.add(mockedSone);
188                         return mockedSone;
189                 }
190
191         }
192
193         public class PostMocker {
194
195                 private final Post post = mock(Post.class);
196                 private final String id;
197                 private final Sone sone;
198                 private Optional<String> recipientId = absent();
199                 private long time;
200                 private Optional<String> text = absent();
201
202                 public PostMocker(String id, Sone sone) {
203                         this.id = id;
204                         this.sone = sone;
205                 }
206
207                 public PostMocker withRecipient(String recipientId) {
208                         this.recipientId = fromNullable(recipientId);
209                         return this;
210                 }
211
212                 public PostMocker withTime(long time) {
213                         this.time = time;
214                         return this;
215                 }
216
217                 public PostMocker withText(String text) {
218                         this.text = fromNullable(text);
219                         return this;
220                 }
221
222                 public Post create() {
223                         when(post.getId()).thenReturn(id);
224                         when(post.getSone()).thenReturn(sone);
225                         when(post.getRecipientId()).thenReturn(recipientId);
226                         if (recipientId.isPresent()) {
227                                 directedPosts.put(recipientId.get(), post);
228                         }
229                         when(post.getTime()).thenReturn(time);
230                         if (text.isPresent()) {
231                                 when(post.getText()).thenReturn(text.get());
232                         }
233                         when(database.getPost(eq(id))).thenReturn(of(post));
234                         sonePosts.put(sone, post);
235                         when(post.getReplies()).then(new Answer<List<PostReply>>() {
236                                 @Override
237                                 public List<PostReply> answer(InvocationOnMock invocation) throws Throwable {
238                                         return Ordering.from(Reply.TIME_COMPARATOR).sortedCopy(postReplies.get(post));
239                                 }
240                         });
241                         return post;
242                 }
243
244         }
245
246         public class PostReplyMocker {
247
248                 private final PostReply postReply = mock(PostReply.class);
249                 private final String id;
250                 private final Sone sone;
251                 private Optional<Post> post = absent();
252                 private long time;
253                 private Optional<String> text = absent();
254
255                 public PostReplyMocker(String id, Sone sone) {
256                         this.id = id;
257                         this.sone = sone;
258                 }
259
260                 public PostReplyMocker inReplyTo(Post post) {
261                         this.post = fromNullable(post);
262                         return this;
263                 }
264
265                 public PostReplyMocker withTime(long time) {
266                         this.time = time;
267                         return this;
268                 }
269
270                 public PostReplyMocker withText(String text) {
271                         this.text = fromNullable(text);
272                         return this;
273                 }
274
275                 public PostReply create() {
276                         when(postReply.getId()).thenReturn(id);
277                         when(postReply.getSone()).thenReturn(sone);
278                         when(postReply.getTime()).thenReturn(time);
279                         when(database.getPostReply(eq(id))).thenReturn(of(postReply));
280                         if (post.isPresent()) {
281                                 postReplies.put(post.get(), postReply);
282                         }
283                         if (text.isPresent()) {
284                                 when(postReply.getText()).thenReturn(text.get());
285                         }
286                         return postReply;
287                 }
288         }
289
290 }