// Mock a salary payment library
@Mock SalaryProcessor mockSalaryProcessor;
@Mock TransactionStrategy mockTransactionStrategy;
...
when(mockSalaryProcessor.addStrategy()).thenReturn(mockTransactionStrategy);
when(mockSalaryProcessor.paySalary()).thenReturn(TransactionStrategy.SUCCESS);
MyPaymentService myPaymentService = new MyPaymentService(mockSalaryProcessor);
assertThat(myPaymentService.sendPayment()).isEqualTo(PaymentStatus.SUCCESS);
|
Curious, in this scenario:
ReplyDelete>If you can’t use the real implementation and a fake implementation doesn’t exist (and library owners aren’t able to create one), create a wrapper class that calls the type, and mock this instead.
How do you then unit test this wrapper?
And for this example:
>FakeSalaryProcessor fakeProcessor = new FakeSalaryProcessor();
Isn't this just a mock that's created by hand, instead of generated at runtime by a mocking library?
What's the real difference here? Either way you have an object that's not the live, production type, and just implements the same interface, correct?
You could very reasonably argue that how the mocks are created matter - but they're both mocks (in definition used by Mockito, etc., JS libraries have more granular defs between mocks/fakes/stubs/etc).
Also, you've essentially shifted the problems around upgrading a library from the test class to the wrapper class, you haven't removed it (but you have isolated it - possibly from many tests to one single wrapper, so, sort of a win).
Do you apply this prescription outside of the tests?
One thing that annoys me about this approach is then you see bizarre wrappers where you have someone deciding that "they know best" and completely change the interface to a well documented API provided by a third party.
At the very least, you usually end up replacing a well-documented, maintained third-party API with less well-documented less well-maintained API.
While the intentions are good, here, I think it should be clarified where & how those wrappers are created.
Would you be fine with code, that, wherever possible, wraps third-party code in tests, but passes the real objects in the implementation?
Also - what about objects you (as in a team) do own? I've seen folks wrap those, because "Mocks are bad".
Fundamentally, based on the examples, it doesn't look like you're differentiating between mock/not mock, it looks like you're
differentiating between how the mocks are created, maintained, and used.
If you're not using the same instance type as the one that live code uses, you're using a mock, even if you wrote it yourself, or a third-party maintainer wrote it, and decided to call it a "Fake" instead.
I think people could be wiser about when they reach for reflection (via Mockito, etc), to
create mocks for them.. but mocks themselves .. seem inevitable in unit tests.
Otherwise, you're writing integration tests.