How exactly works Spring JUnit test that uses stubs?

java, junit, spring, spring-test, unit-testing

Solution

You got it.

Most of the time, you don't create a Stub class explicitely though, but use a mocking framework like Mockito which creates it, dynamically, for you. For example:

AccountRepository stub = mock(AccountRepository.class);
authenticator = new AuthenticatorImpl(stub);

when(stub.getAccount("lisa")).thenReturn(new Account(“lisa”, “secret”));

Problem

I am studying for the Spring Core certification and I have some doubts about how exactly works the unit test with stubs. For example I have the following slide: So I think that it means that in the production environment I have an AuthenticatorImpl class that use a JpaAccountRepo service\repository that is a dependency and it is itself related to some dependencies and to the prodution environment (Spring, configurations and the DB). So if I want to test AuthenticatorImpl as a unit I have to remove links to all dependencies. So using stub way I have to create a stub of the previous first dependency of the unit that I want to test. In this case it is JpaAccountRepo so I can create a generic AccountRepoStub that is a fake implementation that don't use a database and don't use a specific tecnology to access data (I am not testing JpaAccountRepo so I can use a fake implementation because it is a unit test and not an integration test). Is it my reasoning right untill now? So for example if this is my AuthenticatorImpl class ``` public class AuthenticatorImpl implements Authenticator { private AccountRepository accountRepository; public AuthenticatorImpl(AccountRepository accountRepository) { this.accountRepository = accountRepository; } public boolean authenticate(String username, String password) { Account account = accountRepository.getAccount(username); return account.getPassword().equals(password); } } ``` As you can see the constructor AuthenticatorImpl() constructor take a AccountRepository object as paramether (that is an interface and not an implementation). So I can create my stub class named StubAccountRepository that implement AccountRepository interface ``` class StubAccountRepository implements AccountRepository { public Account getAccount(String user) { return “lisa”.equals(user) ? new Account(“lisa”, “secret”) : null; } } ``` So finnally I can create my unit test implementing an AuthenticatorImplTests class ``` import org.junit.Before; import org.junit.Test; ... public class AuthenticatorImplTests { private AuthenticatorImpl authenticator; @Before public void setUp() { authenticator = new AuthenticatorImpl( new StubAccountRepository() ); } @Test public void successfulAuthentication() { assertTrue(authenticator.authenticate(“lisa”, “secret”)); } @Test public void invalidPassword() { assertFalse(authenticator.authenticate(“lisa”, “invalid”)); } } ``` So in my setUp method I build an AuthenticatorImpl object passing to it my stub StubAccountRepository so I removed the link with the dependency and I am testing only the AuthenticatorImpl unit. Is it right or am I missing something? Tnx

Original source