Cool webapps nowadays are made with lot of javascript and boilerplate code. It is almost as bad as EIB. JHipster helps you to get your prototype up and running in minutes (and it takes a lot more time to look arround at all the cool stuff that you do not have to write yourself by hand). But you still have to code your business logic - and of course test it. How does it play together with mocking?
JMockit
There are various mocking framework, but IMHO jmockit is the best option available. It can mockt almost everything (constructores, static methods, abstract clssses, interfaces and watever), and usage is pretty straightforward and logical. How does it play with code generated by jHipster? It plays extremely well.
What to test
JHipster generated me alls the fancy service classes, provided basic CRUD for my entities - but of yourse sometimes you need more. In My case, I like to retrieve service package assotiated with current user, or some reasonable default for anonymous users. Let’s go:
Add libraries to POM
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.39</version>
<scope>test</scope>
</dependency>
No configuration of plugins is necessary - to be active jmockit hat to be on classpath. Take care that it is placed before JUnit - otherwise it will not work
Time to write test
Being a cool developer, I always try to start writing test - before even thinking how I would implement the feature. We start with pretty standard testcase, with Spring-Config etc. We could also bypass it and go for full mocking - but this would expose constructor parameters to test case, and we do not like to test it here.
.class)
@SpringBootTest(classes = TravelexApp.class)
@Transactional
public class ServicePackageServiceTest {
ServicePackageService servicePackageService;
(SpringRunner
Here comes magic:
public void testThatNoUserResultsInDefaultServicePackage(@Mocked UserService userService) {
new Expectations() {{
// no authenticated user
userService.getUserWithAuthorities(); result = Optional.empty();
}};
ServicePackageDTO activePackage = servicePackageService.getActivePackage();
assertThat(activePackage).isNotNull();
assertThat(activePackage.getActivationDate()).isNull();
assertThat(activePackage.getExpirationDate()).isNull();
assertThat(activePackage.getAmountPersons()).isEqualTo(1);
assertThat(activePackage.getAmountTrips()).isEqualTo(1);
}
Just a Testcase - but with Parameters. And this annotation means, that this interface will be completely mocked out for duration of this test. It does not matter, that service gets concrete implementation from spring.
And in expectations object we define how our class under test, shall interact with UserService.
- ask for authenticated user (and discover that there is no such user)
- provide correct service package for this user ( in this case - defaults)
Let’s run out test:
2018-05-10 13:06:15.249 INFO 4608 --- [ main] d.p.t.config.LoggingConfiguration : Filtering metrics logs from all appenders except the LOGSTASH appender
2018-05-10 13:06:20.062 INFO 4608 --- [ main] d.p.t.service.ServicePackageServiceTest : Started ServicePackageServiceTest in 13.992 seconds (JVM running for 16.259)
Missing 1 invocation to:
de.pribluda.travelex.service.UserService#getUserWithAuthorities()
on mock instance: de.pribluda.travelex.service.UserService@59fa5a39
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
It complains about missing invocation of expectd method. Time to complete it:
true)
public ServicePackageDTO getActivePackage() {
Optional<User> userWithAuthorities = userService.getUserWithAuthorities();
if (userWithAuthorities.isPresent()) {
return null;
} else {
return servicePackageMapper.toDto(DEFAULT_PACKAGE);
}
}
(readOnly =
…. and now the test passes:
:: http://www.jhipster.tech ::
2018-05-10 13:51:32.029 INFO 2016 --- [ main] d.p.t.service.ServicePackageServiceTest : Starting ServicePackageServiceTest on deffm-n0167 with PID 2016 (started by Pribludak in C:\vwd\travelex)
2018-05-10 13:51:32.032 INFO 2016 --- [ main] d.p.t.service.ServicePackageServiceTest : No active profile set, falling back to default profiles: default
2018-05-10 13:51:35.541 INFO 2016 --- [ main] d.p.t.config.MetricsConfiguration : Initializing Metrics Log reporting
2018-05-10 13:51:40.033 INFO 2016 --- [ main] d.p.t.config.LoggingConfiguration : Initializing Logstash logging
2018-05-10 13:51:40.164 INFO 2016 --- [ main] d.p.t.config.LoggingConfiguration : Filtering metrics logs from all appenders except the LOGSTASH appender
2018-05-10 13:51:47.196 INFO 2016 --- [ main] d.p.t.service.ServicePackageServiceTest : Started ServicePackageServiceTest in 17.307 seconds (JVM running for 19.575)
2018-05-10 13:51:47.667 WARN 2016 --- [ Thread-6] o.s.b.f.support.DisposableBeanAdapter : Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLException: Die Datenbank wurde bereits geschlossen (um das automatische Schliessen beim Stopp der VM zu deaktivieren, die Datenbank URL mit ";DB_CLOSE_ON_EXIT=FALSE" ergänzen)
Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-197]
Process finished with exit code 0
So, JHipster and JMockit play together - nice. Now i can have easy test driven development with jHipster