Mocking the real world for fun and profit

— Mihai Balan, QE Dev @ Adobe Identity

In object-oriented programming, mock objects are simulated objects that mimic the behavior of real objects in controlled ways. A programmer typically creates a mock object to test the behavior of some other object, in much the same way that a car designer uses a crash test dummy to simulate the dynamic behavior of a human in vehicle impacts.
— Wikipedia [citation needed]

Stories of mocking

  1. πŸ“” The mocking textbook 101
  2. πŸ€ͺ “When I’m alone at night, I Google myself”
  3. πŸ“΅ “Nu rΔƒspunzi la SMS”

πŸ“” Textbook mocking

OOP and polymorphism make it easy to swap components as long as they preserve the interface

DI makes it even easier, by decoupling resource usage and creation
– some solutions can even hotswap

πŸ“” The system under test

Brand new micro-service, built with
β˜• Java OOP all the things!
πŸƒ Spring DI all the things!

External dependencies:
🐬 Database (MySQL)
πŸ“‘ Persistent cache (Redis)
πŸ—„ Logging
etc.

πŸ“” Integration testing in the small

Tests multiple components in concert

Lighter-weight than full-blown integration tests

No network involved

No need to boot-up the app server

Spring-supported, developers-approved πŸ€‘

πŸ“” Integration testing in the small – in practice

Mock what you don’t care about with Mockito

Mock shallowly what you do care about

Use MockMVC to simulate requests to your endpoints and get the responses

Enjoy TestNG πŸ₯‚

πŸ“” Integration testing in the small – in practice

//The declaration in the micro service
@Autowired
private CacheService redisCache;
…
// Somewhere else, in a file far away – our mock "Redis"
@Service
public class ExpiringMapCacheService implements CacheService {
    private final Map<CacheKey, ExpirableValue> map =
        Collections.synchronizedMap(
            new PassiveExpiringMap<>((key, value) -> value.expire)
        );

    @Override
    public <T> T get(CacheKey key) { … }
    // and all the other methods a respectable CacheService has
}

πŸ“” Integration testing in the small – in practice

@Test
public void myTest() throws Exception {
MvcResult mvcResult = createRequest.prepare()
    .withAuthor(AUTHOR_ID).withBody(BODY_PAYLOAD)
    .create()
    .andExpect(status().isCreated()).andReturn();

ResourceResponse createResponse =
    ResourceResponse.fromMvcResult(mvcResult, mapper);

assertEquals(createResponse.getId(), cacheService.get(KEY).getId());
}

πŸ“” Was it worth it?

We caught some timing-sensitive bugs

We expanded the build-time test suite

Easier debugging for failing tests
✨ happy developers ✨

πŸ€ͺ When I’m alone at night, I Google myself

Support login with social accounts

First implemented Facebook support
πŸ’– MUCH TESTING FRIENDLY. SUCH WOW
😿 SUCH SLOW. MUCH FLAKY

Now add Google too 😱

πŸ€ͺ Can we test Google?

No way to create test accounts
– without a real phone number behind them

Difficult to automate login from AWS
– unless you still have that phone number

Some tests need fresh, never-before-seen users
– CI, baby! πŸ”΄πŸ”΅

πŸ€ͺ How did we do it?

🐍 + AWS = πŸ‘

Reverse engineer the APIs

Reverse engineer the UI πŸ€”

Configurable Google endpoints

πŸ€ͺ Was it worth it?

We were able to test!

Easier debugging while developing the feature

Decreased test run times

Fun! 🐍

πŸ“΅ Nu rΔƒspunzi la SMS

Add option to reset password via text message

Provider had a staging environment for feature development

Need to do performance testing on our side of the service πŸ’ΈπŸ’ΈπŸ’Έ

πŸ“΅ Performance testing gotchas

Provider’s staging environment
– not fast enough

NOP-ing the calls to the external services
– not an option

Don’t break the bank
– if at all possible

πŸ“΅ A mock was born

β˜• Java, πŸƒ Spring, and not much else

Deployed on AWS, accessible over the Internet

Exposing same API, but always returning success

Product code was already instrumented

πŸ€– + πŸ€– = πŸ’ͺ

πŸ“΅ Was it worth it?

Very πŸ’°πŸ’°πŸ’° much

+100 XP for our DevOps skills

Paved the way for other creative mocks

Closing remarks

πŸ”§ Mocking can be used in many situations

πŸ’» Being able to use mocking might require developer effort
– don’t think just about mocking, but testability in general

🚲 Don’t reinvent the wheel; unless it’s cheaper

Thank you!

Colophon

Built with β™₯ in Sublime Text, using reveal.js

Dummy from mompl on flickr

Hands from Lauryn on flickr

Fair trade emojis sourced from Emojipedia; responsibly rendered using ✨twEmoji✨