You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Mockito is easy to use when the test needs to provide canned values for a
certain method.
But it gets harder when a canned value isn't sufficient.
======Example 1: Fake with trivial Logic========
interface UserAccount {
List<String> getEmails();
void addEmail(String email);
// 12 other methods ...
}
When mocking such domain entity object, it's tedious to manually program
getEmails()/addEmail() with when().thenReturn() and to make sure the two
methods are logically consistent, that is, getEmails() returns all emails added.
======Example 2: callback-style API======
interface AccountService {
void getAccount(String id, AsyncCallback<UserAccount> callback);
}
Stubbing AccountService isn't easy. It'd require use of Answer, and the Answer
API isn't statically type safe:
when(service.getAccount(eq(id), any(AsyncCallback.class)).thenAnswer(new
Answer<Void>() {
AsyncCallback<UserAccount> callback = (AsyncCallback<UserAccount>) getArguments()[1];
...
});
======Example 3: Uninteresting parameters======
interface AccountRpcService {
FutureAccount getAccount(RpcContext context, String id);
}
None of the tests care about the context object. It's an uninteresting
parameter imposed by the framework.
If AccountRpcService were directly mocked, all tests would have to use isA() to
repetitively mention this uninteresting parameter, like this:
when(service.getAccount(isA(RpcContext.class), eq("id")).thenReturn(...);
And all other parameters are required to be wrapped in eq().
************Proposal************
I propose adding support for abstract classes to mockito to make it easier to
deal with tests like above:
======For example 1======
abstract class FakeUserAccount implements UserAccount {
private final List<String> emails = new ArrayList<>();
@Override public void addEmail(String email) {
emails.add(email);
}
@Override List<String> getEmails() {
return ImmutableList.copyOf(emails);
}
}
@Fake private FakeUserAccount userAccount; // Mockito instantiates abstract
class.
======For example 2======
abstract class MockAccountService implements AccountService {
@Override public void getAccount(String id, AsyncCallback<UserAccount> callback) {
callback.onSuccess(getAccount(id));
}
abstract UserAccount getAccount(String id);
}
@Fake private MockAccountService service;
...
when(service.getAccount("id")).thenReturn(account);
======For example 3======
abstract class MockAccountRpcService implements AccountRpcService {
@Override Future<Account> getAccount(RpcContext context, String id) {
checkNotNull(context); // Common sanity test. Don't have to repeat it in tests.
return getAccount(id);
}
abstract Future<Account> getAccount(String id);
}
@Fake private MockAccountRpcService service;
when(service.getAccount("id")).thenReturn(...);
My work place internally implemented a default Answer to support abstract
classes. We found that the support of abstract classes helps us to avoid
overusing mocks when we should be using fakes. And in situations like above we
get cleaner test code.
But because it's not integrated in the core Mockito, there are gotchas with our
implementation (like, you can't have private/final methods in your fake).
If the idea sounds okay to give a try, I'll volunteer to submit a patch.
Thanks!
Original issue reported on code.google.com by be...@google.com on 22 Sep 2014 at 9:42
The text was updated successfully, but these errors were encountered:
Hi ben, could you submit this as an issue or PR on github, we are likely to
drop googlecode at some point.
Thanks in advance.
Also take a look at issue 242, there have been discussion and uncertainty as to
support partial mocks. As it can bring another way to test/design stuff the
wrong way.
Original comment by brice.du...@gmail.com on 30 Sep 2014 at 11:30
Original issue reported on code.google.com by
be...@google.com
on 22 Sep 2014 at 9:42The text was updated successfully, but these errors were encountered: