Essa dica: é muito importante para quem faz testes unitários!
Imagine uma service com 2 métodos que possuem a mesma validação (IF) como abaixo:
<span>@Service</span><span>@RequiredArgsConstructor</span><span>public</span> <span>class</span> <span>PersonService</span> <span>{</span><span>private</span> <span>static</span> <span>final</span> <span>int</span> <span>ADULT_AGE</span> <span>=</span> <span>18</span><span>;</span><span>public</span> <span>void</span> <span>createAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span><span>if</span> <span>(</span><span>ADULT_AGE</span> <span>></span> <span>Period</span><span>.</span><span>between</span><span>(</span><span>person</span><span>.</span><span>birthdate</span><span>(),</span> <span>LocalDate</span><span>.</span><span>now</span><span>()).</span><span>getYears</span><span>())</span> <span>{</span><span>throw</span> <span>new</span> <span>UnsupportedOperationException</span><span>(</span><span>"person.is.not.adult"</span><span>);</span><span>}</span><span>}</span><span>public</span> <span>void</span> <span>registerCNH</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span><span>if</span> <span>(</span><span>ADULT_AGE</span> <span>></span> <span>Period</span><span>.</span><span>between</span><span>(</span><span>person</span><span>.</span><span>birthdate</span><span>(),</span> <span>LocalDate</span><span>.</span><span>now</span><span>()).</span><span>getYears</span><span>())</span> <span>{</span><span>throw</span> <span>new</span> <span>UnsupportedOperationException</span><span>(</span><span>"person.is.not.adult"</span><span>);</span><span>}</span><span>}</span><span>}</span><span>@Service</span> <span>@RequiredArgsConstructor</span> <span>public</span> <span>class</span> <span>PersonService</span> <span>{</span> <span>private</span> <span>static</span> <span>final</span> <span>int</span> <span>ADULT_AGE</span> <span>=</span> <span>18</span><span>;</span> <span>public</span> <span>void</span> <span>createAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span> <span>if</span> <span>(</span><span>ADULT_AGE</span> <span>></span> <span>Period</span><span>.</span><span>between</span><span>(</span><span>person</span><span>.</span><span>birthdate</span><span>(),</span> <span>LocalDate</span><span>.</span><span>now</span><span>()).</span><span>getYears</span><span>())</span> <span>{</span> <span>throw</span> <span>new</span> <span>UnsupportedOperationException</span><span>(</span><span>"person.is.not.adult"</span><span>);</span> <span>}</span> <span>}</span> <span>public</span> <span>void</span> <span>registerCNH</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span> <span>if</span> <span>(</span><span>ADULT_AGE</span> <span>></span> <span>Period</span><span>.</span><span>between</span><span>(</span><span>person</span><span>.</span><span>birthdate</span><span>(),</span> <span>LocalDate</span><span>.</span><span>now</span><span>()).</span><span>getYears</span><span>())</span> <span>{</span> <span>throw</span> <span>new</span> <span>UnsupportedOperationException</span><span>(</span><span>"person.is.not.adult"</span><span>);</span> <span>}</span> <span>}</span> <span>}</span>@Service @RequiredArgsConstructor public class PersonService { private static final int ADULT_AGE = 18; public void createAdult(final PersonDomain person) { if (ADULT_AGE > Period.between(person.birthdate(), LocalDate.now()).getYears()) { throw new UnsupportedOperationException("person.is.not.adult"); } } public void registerCNH(final PersonDomain person) { if (ADULT_AGE > Period.between(person.birthdate(), LocalDate.now()).getYears()) { throw new UnsupportedOperationException("person.is.not.adult"); } } }
Enter fullscreen mode Exit fullscreen mode
Há uma replicação de código: IF + exceção.
Se o projeto tivesse testes unitários, para ter a cobertura teria que ser algo como o código abaixo:
<span>@ExtendWith</span><span>(</span><span>MockitoExtension</span><span>.</span><span>class</span><span>)</span><span>class</span> <span>PersonServiceTest</span> <span>{</span><span>@InjectMocks</span><span>private</span> <span>PersonService</span> <span>service</span><span>;</span><span>@Nested</span><span>class</span> <span>WhenCreateAdult</span> <span>{</span><span>@Test</span><span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>18</span><span>));</span><span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>createAdult</span><span>(</span><span>person</span><span>));</span><span>}</span><span>@Test</span><span>void</span> <span>shouldDoesNotThrow2</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>19</span><span>));</span><span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>createAdult</span><span>(</span><span>person</span><span>));</span><span>}</span><span>@Test</span><span>void</span> <span>shouldThrow</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>17</span><span>));</span><span>assertThatThrownBy</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>createAdult</span><span>(</span><span>person</span><span>))</span><span>.</span><span>isInstanceOf</span><span>(</span><span>UnsupportedOperationException</span><span>.</span><span>class</span><span>)</span><span>.</span><span>hasMessage</span><span>(</span><span>"person.is.not.adult"</span><span>);</span><span>}</span><span>}</span><span>@Nested</span><span>class</span> <span>WhenRegisterCNH</span> <span>{</span><span>@Test</span><span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>18</span><span>));</span><span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>registerCNH</span><span>(</span><span>person</span><span>));</span><span>}</span><span>@Test</span><span>void</span> <span>shouldDoesNotThrow2</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>19</span><span>));</span><span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>registerCNH</span><span>(</span><span>person</span><span>));</span><span>}</span><span>@Test</span><span>void</span> <span>shouldThrow</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>17</span><span>));</span><span>assertThatThrownBy</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>registerCNH</span><span>(</span><span>person</span><span>))</span><span>.</span><span>isInstanceOf</span><span>(</span><span>UnsupportedOperationException</span><span>.</span><span>class</span><span>)</span><span>.</span><span>hasMessage</span><span>(</span><span>"person.is.not.adult"</span><span>);</span><span>}</span><span>}</span><span>}</span><span>@ExtendWith</span><span>(</span><span>MockitoExtension</span><span>.</span><span>class</span><span>)</span> <span>class</span> <span>PersonServiceTest</span> <span>{</span> <span>@InjectMocks</span> <span>private</span> <span>PersonService</span> <span>service</span><span>;</span> <span>@Nested</span> <span>class</span> <span>WhenCreateAdult</span> <span>{</span> <span>@Test</span> <span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>18</span><span>));</span> <span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>createAdult</span><span>(</span><span>person</span><span>));</span> <span>}</span> <span>@Test</span> <span>void</span> <span>shouldDoesNotThrow2</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>19</span><span>));</span> <span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>createAdult</span><span>(</span><span>person</span><span>));</span> <span>}</span> <span>@Test</span> <span>void</span> <span>shouldThrow</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>17</span><span>));</span> <span>assertThatThrownBy</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>createAdult</span><span>(</span><span>person</span><span>))</span> <span>.</span><span>isInstanceOf</span><span>(</span><span>UnsupportedOperationException</span><span>.</span><span>class</span><span>)</span> <span>.</span><span>hasMessage</span><span>(</span><span>"person.is.not.adult"</span><span>);</span> <span>}</span> <span>}</span> <span>@Nested</span> <span>class</span> <span>WhenRegisterCNH</span> <span>{</span> <span>@Test</span> <span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>18</span><span>));</span> <span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>registerCNH</span><span>(</span><span>person</span><span>));</span> <span>}</span> <span>@Test</span> <span>void</span> <span>shouldDoesNotThrow2</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>19</span><span>));</span> <span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>registerCNH</span><span>(</span><span>person</span><span>));</span> <span>}</span> <span>@Test</span> <span>void</span> <span>shouldThrow</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>17</span><span>));</span> <span>assertThatThrownBy</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>registerCNH</span><span>(</span><span>person</span><span>))</span> <span>.</span><span>isInstanceOf</span><span>(</span><span>UnsupportedOperationException</span><span>.</span><span>class</span><span>)</span> <span>.</span><span>hasMessage</span><span>(</span><span>"person.is.not.adult"</span><span>);</span> <span>}</span> <span>}</span> <span>}</span>@ExtendWith(MockitoExtension.class) class PersonServiceTest { @InjectMocks private PersonService service; @Nested class WhenCreateAdult { @Test void shouldDoesNotThrow() { final var person = new PersonDomain(LocalDate.now().minusYears(18)); assertDoesNotThrow(() -> service.createAdult(person)); } @Test void shouldDoesNotThrow2() { final var person = new PersonDomain(LocalDate.now().minusYears(19)); assertDoesNotThrow(() -> service.createAdult(person)); } @Test void shouldThrow() { final var person = new PersonDomain(LocalDate.now().minusYears(17)); assertThatThrownBy(() -> service.createAdult(person)) .isInstanceOf(UnsupportedOperationException.class) .hasMessage("person.is.not.adult"); } } @Nested class WhenRegisterCNH { @Test void shouldDoesNotThrow() { final var person = new PersonDomain(LocalDate.now().minusYears(18)); assertDoesNotThrow(() -> service.registerCNH(person)); } @Test void shouldDoesNotThrow2() { final var person = new PersonDomain(LocalDate.now().minusYears(19)); assertDoesNotThrow(() -> service.registerCNH(person)); } @Test void shouldThrow() { final var person = new PersonDomain(LocalDate.now().minusYears(17)); assertThatThrownBy(() -> service.registerCNH(person)) .isInstanceOf(UnsupportedOperationException.class) .hasMessage("person.is.not.adult"); } } }
Enter fullscreen mode Exit fullscreen mode
Terá então replicação de código e de teste unitário.
É comum para evitar a replicação de código, separar em outra classe e reaproveitar o mesmo código.
<span>public</span> <span>class</span> <span>PersonValidator</span> <span>{</span><span>private</span> <span>static</span> <span>final</span> <span>int</span> <span>ADULT_AGE</span> <span>=</span> <span>18</span><span>;</span><span>public</span> <span>static</span> <span>void</span> <span>verifyAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span><span>if</span> <span>(</span><span>ADULT_AGE</span> <span>></span> <span>Period</span><span>.</span><span>between</span><span>(</span><span>person</span><span>.</span><span>birthdate</span><span>(),</span> <span>LocalDate</span><span>.</span><span>now</span><span>()).</span><span>getYears</span><span>())</span> <span>{</span><span>throw</span> <span>new</span> <span>UnsupportedOperationException</span><span>(</span><span>"person.is.not.adult"</span><span>);</span><span>}</span><span>}</span><span>}</span><span>public</span> <span>class</span> <span>PersonValidator</span> <span>{</span> <span>private</span> <span>static</span> <span>final</span> <span>int</span> <span>ADULT_AGE</span> <span>=</span> <span>18</span><span>;</span> <span>public</span> <span>static</span> <span>void</span> <span>verifyAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span> <span>if</span> <span>(</span><span>ADULT_AGE</span> <span>></span> <span>Period</span><span>.</span><span>between</span><span>(</span><span>person</span><span>.</span><span>birthdate</span><span>(),</span> <span>LocalDate</span><span>.</span><span>now</span><span>()).</span><span>getYears</span><span>())</span> <span>{</span> <span>throw</span> <span>new</span> <span>UnsupportedOperationException</span><span>(</span><span>"person.is.not.adult"</span><span>);</span> <span>}</span> <span>}</span> <span>}</span>public class PersonValidator { private static final int ADULT_AGE = 18; public static void verifyAdult(final PersonDomain person) { if (ADULT_AGE > Period.between(person.birthdate(), LocalDate.now()).getYears()) { throw new UnsupportedOperationException("person.is.not.adult"); } } }
Enter fullscreen mode Exit fullscreen mode
Na service o código ficaria.
<span>@Service</span><span>@RequiredArgsConstructor</span><span>public</span> <span>class</span> <span>PersonService</span> <span>{</span><span>public</span> <span>void</span> <span>createAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span><span>PersonValidator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span><span>}</span><span>public</span> <span>void</span> <span>registerCNH</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span><span>PersonValidator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span><span>}</span><span>}</span><span>@Service</span> <span>@RequiredArgsConstructor</span> <span>public</span> <span>class</span> <span>PersonService</span> <span>{</span> <span>public</span> <span>void</span> <span>createAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span> <span>PersonValidator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span> <span>}</span> <span>public</span> <span>void</span> <span>registerCNH</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span> <span>PersonValidator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span> <span>}</span> <span>}</span>@Service @RequiredArgsConstructor public class PersonService { public void createAdult(final PersonDomain person) { PersonValidator.verifyAdult(person); } public void registerCNH(final PersonDomain person) { PersonValidator.verifyAdult(person); } }
Enter fullscreen mode Exit fullscreen mode
OK, foi resolvido a replicação do IF e do throw, porém o teste unitário ainda está replicado! E por isso é recomendado sempre usar Bean’s! Evitar o uso de métodos estáticos e transformar a classe em uma Bean.
<span>@Component</span><span>public</span> <span>class</span> <span>PersonValidator</span> <span>{</span><span>private</span> <span>static</span> <span>final</span> <span>int</span> <span>ADULT_AGE</span> <span>=</span> <span>18</span><span>;</span><span>public</span> <span>void</span> <span>verifyAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span><span>if</span> <span>(</span><span>ADULT_AGE</span> <span>></span> <span>Period</span><span>.</span><span>between</span><span>(</span><span>person</span><span>.</span><span>birthdate</span><span>(),</span> <span>LocalDate</span><span>.</span><span>now</span><span>()).</span><span>getYears</span><span>())</span> <span>{</span><span>throw</span> <span>new</span> <span>UnsupportedOperationException</span><span>(</span><span>"person.is.not.adult"</span><span>);</span><span>}</span><span>}</span><span>}</span><span>@Component</span> <span>public</span> <span>class</span> <span>PersonValidator</span> <span>{</span> <span>private</span> <span>static</span> <span>final</span> <span>int</span> <span>ADULT_AGE</span> <span>=</span> <span>18</span><span>;</span> <span>public</span> <span>void</span> <span>verifyAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span> <span>if</span> <span>(</span><span>ADULT_AGE</span> <span>></span> <span>Period</span><span>.</span><span>between</span><span>(</span><span>person</span><span>.</span><span>birthdate</span><span>(),</span> <span>LocalDate</span><span>.</span><span>now</span><span>()).</span><span>getYears</span><span>())</span> <span>{</span> <span>throw</span> <span>new</span> <span>UnsupportedOperationException</span><span>(</span><span>"person.is.not.adult"</span><span>);</span> <span>}</span> <span>}</span> <span>}</span>@Component public class PersonValidator { private static final int ADULT_AGE = 18; public void verifyAdult(final PersonDomain person) { if (ADULT_AGE > Period.between(person.birthdate(), LocalDate.now()).getYears()) { throw new UnsupportedOperationException("person.is.not.adult"); } } }
Enter fullscreen mode Exit fullscreen mode
A PersonService com a injeção de dependência da nova Bean.
<span>@Service</span><span>@RequiredArgsConstructor</span><span>public</span> <span>class</span> <span>PersonService</span> <span>{</span><span>private</span> <span>final</span> <span>PersonValidator</span> <span>validator</span><span>;</span><span>public</span> <span>void</span> <span>createAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span><span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span><span>}</span><span>public</span> <span>void</span> <span>registerCNH</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span><span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span><span>}</span><span>}</span><span>@Service</span> <span>@RequiredArgsConstructor</span> <span>public</span> <span>class</span> <span>PersonService</span> <span>{</span> <span>private</span> <span>final</span> <span>PersonValidator</span> <span>validator</span><span>;</span> <span>public</span> <span>void</span> <span>createAdult</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span> <span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span> <span>}</span> <span>public</span> <span>void</span> <span>registerCNH</span><span>(</span><span>final</span> <span>PersonDomain</span> <span>person</span><span>)</span> <span>{</span> <span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span> <span>}</span> <span>}</span>@Service @RequiredArgsConstructor public class PersonService { private final PersonValidator validator; public void createAdult(final PersonDomain person) { validator.verifyAdult(person); } public void registerCNH(final PersonDomain person) { validator.verifyAdult(person); } }
Enter fullscreen mode Exit fullscreen mode
O teste unitário fica único.
<span>@ExtendWith</span><span>(</span><span>MockitoExtension</span><span>.</span><span>class</span><span>)</span><span>class</span> <span>PersonValidatorTest</span> <span>{</span><span>@InjectMocks</span><span>private</span> <span>PersonValidator</span> <span>validator</span><span>;</span><span>@Nested</span><span>class</span> <span>WhenVerifyAdult</span> <span>{</span><span>@Test</span><span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>18</span><span>));</span><span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>));</span><span>}</span><span>@Test</span><span>void</span> <span>shouldDoesNotThrow2</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>19</span><span>));</span><span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>));</span><span>}</span><span>@Test</span><span>void</span> <span>shouldThrow</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>17</span><span>));</span><span>assertThatThrownBy</span><span>(()</span> <span>-></span> <span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>))</span><span>.</span><span>isInstanceOf</span><span>(</span><span>UnsupportedOperationException</span><span>.</span><span>class</span><span>)</span><span>.</span><span>hasMessage</span><span>(</span><span>"person.is.not.adult"</span><span>);</span><span>}</span><span>}</span><span>}</span><span>@ExtendWith</span><span>(</span><span>MockitoExtension</span><span>.</span><span>class</span><span>)</span> <span>class</span> <span>PersonValidatorTest</span> <span>{</span> <span>@InjectMocks</span> <span>private</span> <span>PersonValidator</span> <span>validator</span><span>;</span> <span>@Nested</span> <span>class</span> <span>WhenVerifyAdult</span> <span>{</span> <span>@Test</span> <span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>18</span><span>));</span> <span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>));</span> <span>}</span> <span>@Test</span> <span>void</span> <span>shouldDoesNotThrow2</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>19</span><span>));</span> <span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>));</span> <span>}</span> <span>@Test</span> <span>void</span> <span>shouldThrow</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>().</span><span>minusYears</span><span>(</span><span>17</span><span>));</span> <span>assertThatThrownBy</span><span>(()</span> <span>-></span> <span>validator</span><span>.</span><span>verifyAdult</span><span>(</span><span>person</span><span>))</span> <span>.</span><span>isInstanceOf</span><span>(</span><span>UnsupportedOperationException</span><span>.</span><span>class</span><span>)</span> <span>.</span><span>hasMessage</span><span>(</span><span>"person.is.not.adult"</span><span>);</span> <span>}</span> <span>}</span> <span>}</span>@ExtendWith(MockitoExtension.class) class PersonValidatorTest { @InjectMocks private PersonValidator validator; @Nested class WhenVerifyAdult { @Test void shouldDoesNotThrow() { final var person = new PersonDomain(LocalDate.now().minusYears(18)); assertDoesNotThrow(() -> validator.verifyAdult(person)); } @Test void shouldDoesNotThrow2() { final var person = new PersonDomain(LocalDate.now().minusYears(19)); assertDoesNotThrow(() -> validator.verifyAdult(person)); } @Test void shouldThrow() { final var person = new PersonDomain(LocalDate.now().minusYears(17)); assertThatThrownBy(() -> validator.verifyAdult(person)) .isInstanceOf(UnsupportedOperationException.class) .hasMessage("person.is.not.adult"); } } }
Enter fullscreen mode Exit fullscreen mode
E o teste unitário na PersonService torna-se apenas um verify.
<span>@ExtendWith</span><span>(</span><span>MockitoExtension</span><span>.</span><span>class</span><span>)</span><span>class</span> <span>PersonServiceTest</span> <span>{</span><span>@InjectMocks</span><span>private</span> <span>PersonService</span> <span>service</span><span>;</span><span>@Mock</span><span>private</span> <span>PersonValidator</span> <span>validator</span><span>;</span><span>@Nested</span><span>class</span> <span>WhenCreateAdult</span> <span>{</span><span>@Test</span><span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>());</span><span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>createAdult</span><span>(</span><span>person</span><span>));</span><span>verify</span><span>(</span><span>validator</span><span>).</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span><span>}</span><span>}</span><span>@Nested</span><span>class</span> <span>WhenRegisterCNH</span> <span>{</span><span>@Test</span><span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span><span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>());</span><span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>registerCNH</span><span>(</span><span>person</span><span>));</span><span>verify</span><span>(</span><span>validator</span><span>).</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span><span>}</span><span>}</span><span>}</span><span>@ExtendWith</span><span>(</span><span>MockitoExtension</span><span>.</span><span>class</span><span>)</span> <span>class</span> <span>PersonServiceTest</span> <span>{</span> <span>@InjectMocks</span> <span>private</span> <span>PersonService</span> <span>service</span><span>;</span> <span>@Mock</span> <span>private</span> <span>PersonValidator</span> <span>validator</span><span>;</span> <span>@Nested</span> <span>class</span> <span>WhenCreateAdult</span> <span>{</span> <span>@Test</span> <span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>());</span> <span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>createAdult</span><span>(</span><span>person</span><span>));</span> <span>verify</span><span>(</span><span>validator</span><span>).</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span> <span>}</span> <span>}</span> <span>@Nested</span> <span>class</span> <span>WhenRegisterCNH</span> <span>{</span> <span>@Test</span> <span>void</span> <span>shouldDoesNotThrow</span><span>()</span> <span>{</span> <span>final</span> <span>var</span> <span>person</span> <span>=</span> <span>new</span> <span>PersonDomain</span><span>(</span><span>LocalDate</span><span>.</span><span>now</span><span>());</span> <span>assertDoesNotThrow</span><span>(()</span> <span>-></span> <span>service</span><span>.</span><span>registerCNH</span><span>(</span><span>person</span><span>));</span> <span>verify</span><span>(</span><span>validator</span><span>).</span><span>verifyAdult</span><span>(</span><span>person</span><span>);</span> <span>}</span> <span>}</span> <span>}</span>@ExtendWith(MockitoExtension.class) class PersonServiceTest { @InjectMocks private PersonService service; @Mock private PersonValidator validator; @Nested class WhenCreateAdult { @Test void shouldDoesNotThrow() { final var person = new PersonDomain(LocalDate.now()); assertDoesNotThrow(() -> service.createAdult(person)); verify(validator).verifyAdult(person); } } @Nested class WhenRegisterCNH { @Test void shouldDoesNotThrow() { final var person = new PersonDomain(LocalDate.now()); assertDoesNotThrow(() -> service.registerCNH(person)); verify(validator).verifyAdult(person); } } }
Enter fullscreen mode Exit fullscreen mode
Obtém-se o mesmo resultado com o mesmo objetivo e ainda mantém boas práticas de código e testes.
No exemplo foi utilizado apenas um método com retorno void e utilizado apenas em dois locais do sistema, porém esse exemplo se aplica a cenários mais complexos onde condicionais ou estados de objetos influenciam e alteram os comportamentos dos componentes do sistema em N locais. Essa dica torna mais fácil, mais eficiente e menos desgastantes os testes unitários.
暂无评论内容