Maven: Überblick für Entwickler

February 16, 2024 @ 09:00 16:00

Schulung / Training / Kurs / Seminar – 1 Tag remote

Apache Maven ist seit mehr als einem Jahrzehnt als Build– und Reporting-Tool für Java-Projekte etabliert. Der Erfolg dieses Werkzeuges begründete sich vor allem in der einfacheren Lösung des Abhängigkeitsmanagements fremder Programmbibliotheken. Entwickler lassen in ihren Projekten mehrmals täglich lokale Maven Builds laufen, wissen aber oft nicht, wie sie bei Problemen Abhilfe schaffen können.

In diesem Workshop lernen Sie die wichtigsten Grundlagen zu Maven kennen. Schnell gehen wir zu fortgeschrittenen Themen über und lernen wie der Build Lifecycle nicht nur über die Build Logik, sondern auch über die Kommandozeile beeinflusst werden kann. Es handelt sich um einen praxis-orientierten Workshop mit vielen Beispielen aus dem Entwickleralltag.

Durchführungs-Garantie: der Kurs wird auch bei nur einem Teilenmer:in durchgeführt.

Kurs buchen: https://www.gfu.net/seminare-schulungen-kurse/testmanagement_sk92/maven-ueberblick-fuer-entwickler_s2345.html

Jede(r) Teilnehmer(in) erhält eine gedruckte Ausgabe des Buches: Marco Schulz, CI mit Jenkins, Rheinwerk, 2021

Sollten Sie zu den angebotenen Terminen nicht können, beziehungsweise für Ihr Team einen individuellen Termin wünschen, um beispielsweise in einer geschlossenen Runde auf konkrete Problemstellungen eingehen zu können, besteht die Möglichkeit zusätzliche außerplanmäßige Termine zu vereinbaren. Nutzen Sie bitte hierzu mein Kontaktformular unter der Angabe welchen Kurs Sie wünschen, mit Terminvorschlägen und der zu erwartenden Teilnehmerzahl.

Weitere Termine:

  • 10.05.2024
  • 23.08.2024
  • 15.11.2024

DevOps – Praxistraining – Entwicklung, Test, Monitoring und Logging

December 11 @ 09:00 December 13 @ 16:00

Schulung / Training / Kurs / Seminar – 3 Tage remote

Wenn ein Unternehmen sich entscheidet, Software nach der DevOps-Philosophie zu entwickeln, bietet sich eine große Chance, den Kunden robustere Software in kürzeren Entwicklungszyklen bereit zu stellen. Gemeinsam müssen alle Beteiligten die Unternehmenskultur so verändern, dass Konzeption, Entwicklung, Test und Betrieb von Software Hand in Hand gehen.

Für Entwickler bedeutet dies meist eine deutliche Erweiterung von Anforderungen und Verantwortung: Themen wie Containerisierung, Integrationstests, Monitoring und Logging sollten bedacht und beherrscht werden. In diesem Praxisseminar machen Sie sich anhand ‘echter’ Softwareprojekte mit vielen unterschiedlichen Technologien und Methoden vertraut.

Durchführungs-Garantie: der Kurs wird auch bei nur einem Teilenmenden durchgeführt

Kurs buchen: https://www.gfu.net/seminare-schulungen-kurse/java_sk5/devops-werkzeugkasten-entwickler_s2137.html

Jeder Teilenmende erhält eine gedruckte Ausgabe des Buches: Marco Schulz, CI mit Jenkins, Rheinwerk, 2021

Sollten Sie zu den angebotenen Terminen nicht können, beziehungsweise für Ihr Team einen individuellen Termin wünschen, um beispielsweise in einer geschlossenen Runde auf konkrete Problemstellungen eingehen zu können, besteht die Möglichkeit zusätzliche außerplanmäßige Termine zu vereinbaren. Nutzen Sie bitte hierzu mein Kontaktformular unter der Angabe welchen Kurs Sie wünschen, mit Terminvorschlägen und der zu erwartenden Teilnehmerzahl.

Weitere Termine:

  • 11.03 – 13.03.2024
  • 10.06 – 12.06.2024

JPoint Moscow 2023

April 12 All day

Test Driven: from zero to hero

In the software industry, it is a common agreement that the code base has sufficient test automation. Because this is necessary for a stable DevOps process and secure refactoring. But the reality is completely different. Almost every project I joined during my career didn’t have any lines of test code. If we think about the fact that after more than 40 years, 80% of all commercial software projects fail, we should not be surprised. But this doesn’t have to be like this. In this talk, we demonstrate how easy it is to introduce, even in huge projects, a test-driven approach. The technical setup is a standard Java project with Apache Maven and JUnit 5.

JCON 2019

September 24, 2019 All day

Testfalle – Richtiges und effizientes Softwaretesten

Das Software getestet werden muss ist allen Beteiligten klar. Oft stellt sich nicht die Frage welche Test Frameworks eingesetzt werden sollten, sondern viel mehr das Wie bereitet die meisten Unklarheiten. Am Beispiel eines realen Open Source Projektes werden zentrale Aspekte des Softwaretesting anschaulich besprochen. Dazu gehören die Punkte:

  • Wie erzeuge ich testbaren Code
  • Wie kann mit einem Testfall die Qualität verbessert werden
  • Was ist Testabdeckung und wo liegen die Grenzen
  • Wer ist für welche Tests zuständig
  • Wie entwickelt man testgetrieben ohne Mehraufwand
  • Wie kann das Management die Testqualität beurteilen

IT-Tage FFM 2020

December 12, 2020 All day

Maven secrets unlocked – verbessern Sie Ihren Build

Apache Maven ist seit mehr als einem Jahrzehnt als Build- und Reporting-Tool für Java-Projekte etabliert. Der Erfolg dieses Tools wurde, weil es als eines der ersten Build-Tools eine einfache Lösung für das Abhängigkeitsmanagement ansprach. Entwickler lassen mehrmals am Tag einen Maven-Build laufen, wissen aber oft nicht, wie sie Probleme beheben können, wenn ein Build kaputt ist.

In diesem praxisorientierten Vortrag beginnen wir mit den Grundlagen und gehen schnell zu fortgeschrittenen Themen über und lernen, wie man den Lebenszyklus eines Builds modifiziert:

  • Token-Ersatz für die Datenbankkonfiguration
  • Ausführbare jar-Dateien
  • Paket-Fat-Jar einschließlich Abhängigkeiten & MANIFEST-Manipulation
  • Arbeiten mit Webanwendungen & Multi-Modul-Projekten
  • Erzwingen von Java-Kompilierungsversionen & Release-Zusammenhängen
  • Konfigurieren der Reporting-Engine

jConf Peru 2021

November 27, 2021 All day

Maven POM demystified: enhance your build

Since more than a decade Apache Maven is one of the most convenient Build and Reporting tools for Java projects. The success of this tool is quit more than just being a build tool. It solves problems in a simple manner. As developer you need run your Maven Build several times, but often the knowledge is missing how to manipulate the build without change the build logic called POM. I will show some tricks how to solve problems when your Maven got stuck. In this presentation I cover regular developer issues and how to overcome them. Because a well working build is more than just a bit of DevOps techniques.

Learn things about token replacement, executable jar, BOM, Dependency Management, enforcement, reporting and much more in live demonstrations.

jConf Peru 2021

November 27, 2021 All day

Mission accomplished: deploy to Maven Central

Many developers have ideas they work on it in their spare time. The most of us are convinced about open source and share their own projects on platforms like GitHub. But what happen after a publication of the source code? If you really want to gain people to use your project you’re not done yet. It’s also a good idea to publish your artifacts for a simple usage.

The most famous storage for binary Java Artifacts is Maven Central. Doesn‘t matter if you use in your projects Ivy, Gradle or Maven as dependency management, all those technologies access to Maven Central. In this talk you will learn how to publish your artifacts with Maven to Sonatype Nexuss OSS. We pass through all steps from creating accounts until the the binaries are available. In between I give some general hints about the usage of repository managers and helpful tricks for a lightweight Release Management.

Learn things about token replacement, executable jar, BOM, Dependency Management, enforcement, reporting and much more in live demonstrations.

Working with JSON in Java RESTful Services using Jackson

Since a long time the Java Script Object Notation [1] become as a lightweight standard to replace XML for information exchange between heterogeneous systems. Both technologies XML and JSON closed those gap to return simple and complex data of a remote method invocation (RMI), when different programming languages got involved. Each of those technologies has its own benefits and disadvantages. A good designed XML document is human readable but needs in comparing to JSON more payload when it send through the network. For almost every programming languages existing plenty implementations to deal with XML and also JSON. We don’t need to reinvent the wheel, to implement our own solution for handling JSON objects. But choosing the right library is not that easy might it seems.

The most popular library for JSON in Java projects is the one I already mentioned: Jackson [2]. because of its huge functionality. Another important point for choosing Jackson instead of other libraries is it’s also used by the Jersey REST Framework [3]. Before we start now our journey with the Java Frameworks Jersey and Jackson, I like to share some thoughts about things, I often observe in huge projects during my professional life. Because of this reason I always proclaim: don’t mix up different implementation libraries for the same technology. The reason is it’s a huge quality and security concern.

The general purpose for using JSON in RESTful applications is to transmit data between a server and a client via HTTP. To achieve that, we need to solve two challenges. First, on the server side, we need create form a Java object a valid JSON representation which we can send to the client. This process we call serialization. On the client side, we do the second step, which is exactly the opposite, we did on the server. De-serialization we call it, when we create a valid object from a JSON String.

In this article we will use on the server side and also on the client side Java as programming language, to deal with JSON objects. But keep in mind REST allows you to have different programming languages on the server and for the client. Java is always a good choice to implement your business logic on the server. The client side often is made with JavaScript. Also PHP, .NET and other programming Languages are possible.

In the next step we will have a look at the project architecture. All artifacts are organized by one Apache Maven Multi-Module project. It’s a good recommendation to follow this structure in your own projects too. The three artifacts we create are: api, server and client.

  • API: contain shared objects which will needed on the server and also client side, like domain objects and interfaces.
  • Server: producer of a RESTful service, depends on API.
  • Client: consumer of the RESTful service, depends on API.

Inside of this artifacts an layer architecture is applied. This means the access to objects from a layer is only allowed to the direction of the underlying layers. In short: from top to down. The layer structure are organized by packages. Not every artifact contains every layer, only the ones which are implemented. The following picture draws an better understanding for the whole architecture is used.

The first piece of code, I’d like to show are the JSON dependencies we will need in the notation for Maven projects.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${version}</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${version}</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${version}</version>
</dependency>
XML

Listing 1

In respect to the size of this article, I only focus how the JSON object is used in RESTful applications. It’s not a full workshop about RESTful (Micro) Services. As code base we reuse my open source GitHub project TP-ACL [4], an access control list. For our example I decided to sliced apart the Role – Functionality from the whole code base.

For now we need as first an Java object which we can serialize to an JSON String. This Domain Object will be the Class RolesDO and is located in the layer domain inside the API module. The roles object contains a name, a description and a flag that indicates if a role is allowed to delete.

@Entity
@Table(name = "ROLES")
public class RolesDO implements Serializable {

    private static final long serialVersionUID = 50L;

    @Id
    @Column(name = "NAME")
    private String name;

    @Column(name = "DESCRIPTION")
    private String description;

    @Column(name = "DELETEABLE")
    private boolean deleteable;

    public RolesDO() {
        this.deleteable = true;
    }

    public RolesDO(final String name) {
        this.name = name;
        this.deleteable = true;
    }

    //Getter & Setter
}
Java

Listing 2

So far so good. As next step we will need to serialize the RolesDO in the server module as a JSON String. This step we will do in the RolesHbmDAO which is stored in the implementation layer within the Server module. The opposite direction, the de-serialization is also implemented in the same class. But slowly, not everything at once. lets have as first a look on the code.

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class RolesDAO {

    public transient EntityManager mainEntityManagerFactory;

    public String serializeAsJson(final RolesDO role) 
            throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(role);
    }

    public RolesDO deserializeJsonAsObject(final String json, final RolesDO role) 
            throws JsonProcessingException, ClassNotFoundException {
        ObjectMapper mapper = new ObjectMapper();
        return (RolesDO) mapper.readValue(json, Class.forName(object.getCanonicalName()));
    }

    public List<RolesDO> deserializeJsonAsList(final String json)
            throws JsonProcessingException, ClassNotFoundException {       
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(json, new TypeReference<List>() {});
    }

    public List listProtectedRoles() {

        CriteriaBuilder builder = mainEntityManagerFactory.getCriteriaBuilder();
        CriteriaQuery query = builder.createQuery(RolesDO.class);
        
        Root root = query.from(RolesDO.class);
        query.where(builder.isNull(root.get("deactivated")));
        query.orderBy(builder.asc(root.get("name")));

        return mainEntityManagerFactory.createQuery(query).getResultList();
    }
}
Java

Listing 3

The implementation is not so difficult to understand, but may at this point could the first question appear. Why the de-serilization is in the server module and not in the client module? When the client sends a JSON to the server module, we need to transform this to an real Java object. Simple as that.

Usually the Data Access Object (DAO) Pattern contains all functionality for database operations. This CRUD (create, read, update and delete) functions, we will jump over. If you like to get to know more about how the DAO pattern is working, you could also check my project TP-CORE [4] at GitHub. Therefore we go ahead to the REST service implemented in the object RoleService. Here we just grep the function fetchRole().

@Service
public class RoleService {

    @Autowired
    private RolesDAO rolesDAO;

    @GET
    @Path("/{role}")
    @Produces({MediaType.APPLICATION_JSON})
    public Response fetchRole(final @PathParam("role") String roleName) {
        Response response = null;
        try {
            RolesDO role = rolesDAO.find(roleName);
            if (role != null) {
                String json = rolesDAO.serializeAsJson(role);
                response = Response.status(Response.Status.OK)
                        .type(MediaType.APPLICATION_JSON)
                        .entity(json)
                        .encoding("UTF-8")
                        .build();
            } else {
                response = Response.status(Response.Status.NOT_FOUND).build();
            }

        } catch (Exception ex) {
            LOGGER.log("ERROR CODE 500 " + ex.getMessage(), LogLevel.DEBUG);
            response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
        }
        return response;
    }
}
Java

Listing 4

The big secret here we have in the line where we stick the things together. As first the RolesDO is created and in the next line the DAO calls the serializeAsJson() Method with the RoleDO as parameter. The result will be a JSON representation of the RoleDO. If the role exist and no exceptions occur, then the service is ready for consuming. In the case of any problem the service send a HTTP error code instead of the JSON.

Complex Services which combine single services to a process take place in the orchestration layer. At this point we can switch to the client module to learn how the JSON String got transformed back to a Java domain object. In the client we don’t have RolesHbmDAO to use the deserializeJsonAsObject() method. And of course we also don’t want to create duplicate code. This forbids us to copy paste the function into the client module.

As pendant to the fetchRole() on the server side, we use for the client getRole(). The purpose of both implementations is identical. The different naming helps to avoid confusions.

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Role {
    private final String API_PATH
            = "/acl/" + Constraints.REST_API_VERSION + "/role";
    private WebTarget target;

    public RolesDO getRole(String role) throws JsonProcessingException {
        Response response = target
                .path(API_PATH).path(role)
                .request()
                .accept(MediaType.APPLICATION_JSON)
                .get(Response.class);
        LOGGER.log("(get) HTTP STATUS CODE: " + response.getStatus(), LogLevel.INFO);

        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(response.readEntity(String.class), RolesDO.class);
    }
}
Java

Listing 5

As conclusion we have now seen the serialization and de-serialisation by using the Jackson library of JSON objects is not that difficult. In the most of the cases we just need three methods:

  • serialize a Java object to a JSON String
  • create a Java object from a JSON String
  • de-serialize a list of objects inside a JSON String to a Java object collection

This three methods I already introduced in Listing 2 for the DAO. To prevent duplicate code we should separte those functionality in an own Java Class. This is known as the design pattern Wrapper [5] also known as Adapter. For reaching the best flexibility I implemented the JacksonJsonTools from TP-CORE as Generic.

package org.europa.together.application;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.core..JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;

public class JacksonJsonTools {

    private static final long serialVersionUID = 15L;

    public String serializeAsJsonObject(final T object)
            throws JsonProcessingException {
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException ex) {
            System.err.println(ex.getOriginalMessage());
        }
    }

    public T deserializeJsonAsObject(final String json, final Class object)
            throws JsonProcessingException, ClassNotFoundException {
        try {
            Class<?> clazz = Class.forName(object.getCanonicalName());
            ObjectMapper mapper = new ObjectMapper();
            return (T) mapper.readValue(json, clazz);
        } catch (JsonProcessingException ex) {
            System.err.println(ex.getOriginalMessage());
        }
    }

    public List deserializeJsonAsList(final String json)
            throws JsonProcessingException, ClassNotFoundException {
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.readValue(json, new TypeReference<List>() {
            });
        } catch (com.fasterxml.jackson.core.JsonProcessingException ex) {
            System.err.println(ex.getOriginalMessage());
        }
    }
}
Java

Listing 6

This and much more useful Implementations with a very stable API you find in my project TP-CORE for free usage.

Resources:

Acceptance Tests in Java With JGiven

published also on DZone 01.2020

Most of the developer community know what a unit test is, even they don’t write them. But there is still hope. The situation is changing. More and more projects hosted on GitHub contain unit tests.

In a standard set-up for Java projects like NetBeans, Maven, and JUnit, it is not that difficult to produce your first test code. Besides, this approach is used in Test Driven Development (TDD) and exists in other technologies like Behavioral Driven Development (BDD), also known as acceptance tests, which is what we will focus on in this article.

Difference Between Unit and Acceptance Tests

The easiest way to become familiar with this topic is to look at a simple comparison between unit and acceptance tests. In this context, unit tests are very low level. They execute a function and compare the output with an expected result. Some people think differently about it, but in our example, the only one responsible for a unit test is the developer.

Keep in mind that the test code is placed in the project and always gets executed when the build is running. This provides quick feedback as to whether or not something went wrong. As long the test doesn’t cover too many aspects, we are able to identify the problem quickly and provide a solution. The design principle of those tests follows the AAA paradigm. Define a precondition (Arrange), execute the invariant (Act), and check the postconditions (Assume). We will come back to this approach a little later.

When we check the test coverage with tools like JaCoCo and cover more than 85 percent of our code with test cases, we can expect good quality. During the increasing test coverage, we specify our test cases more precisely and are able to identify some optimizations. This can be removing or inverting conditions because during the tests we find out, it is almost impossible to reach those sections. Of course, the topic is a bit more complicated, but those details could be discussed in another article.

Acceptance test are same classified like unit tests. They belong to the family of regression tests. This means we want to observe if changes we made on the code have no effects on already worked functionality. In other words, we want to secure that nothing already is working got broken, because of some side effects of our changes. The tool of our choice is JGiven [1]. Before we look at some examples, first, we need to touch on a bit of theory.

JGiven In-Depth

The test cases we define in JGiven is called a scenario. A scenario is a collection of four classes, the scenario itself, the Given displayed as given (Arrange), the Action displayed as when (Act) and Outcome displayed as then (Assume).

In most projects, especially when there is a huge amount of scenarios and the execution consumes a lot of time, acceptance tests got organized in a separate project. With a build job on your CI server, you can execute those tests once a day to get fast feedback and to react early if something is broken. The code example we demonstrate contains everything in one project on GitHub [2] because it is just a small library and a separation would just over-engineer the project. Usually, the one responsible for acceptance tests is the test center, not the developer.

The sample project TP-CORE is organized by a layered architecture. For our example, we picked out the functionality for sending e-mails. The basic functionality to compose an e-mail is realized in the application layer and has a test coverage of up to 90 percent. The functionality to send the e-mail is defined in the service layer.

In our architecture, we decided that the service layer is our center of attention to defining acceptance tests. Here, we want to see if our requirement to send an e-mail is working well. Supporting this layer with our own unit tests is not that efficient because, in commercial projects, it just produces costs without winning benefits. Also, having also unit tests means we have to do double the work because our JGiven tests already demonstrate and prove that our function is well working. For those reasons, it makes no sense to generate test coverage for the test scenarios of the acceptance test.

Let’s start with a practice example. At first, we need to include our acceptance test framework into our Maven build. In case you prefer Gradle, you can use the same GAV parameters to define the dependencies in your build script.

<dependency>
   <groupId>com.tngtech.jgiven</groupId>
   <artifactId>jgiven-junit</artifactId>
   <version>0.18.2</version>
   <scope>test</scope>
</dependency>
XML

Listing 1: Dependency for Maven.

As you can see in listing 1, JGiven works well together with JUnit. An integration to TestNG also exists , you just need to replace the artifactId for jgiven-testng. To enable the HTML reports, you need to configure the Maven plugin in the build lifecycle, like it is shown in Listing 2.

<build> 
   <plugins>
      <plugin>
         <groupId>com.tngtech.jgiven</groupId>
         <artifactId>jgiven-maven-plugin</artifactId>
         <version>0.18.2</version>
         <executions>
            <execution>
               <goals>
                  <goal>report</goal>
               </goals>
            </execution>
         </executions>
         <configuration>
            <format>html</format>
         </configuration>
      </plugin>
   </plugins>
</build>
XML

Listing 2: Maven Plugin Configuration for JGiven.

The report of our scenarios in the TP-CORE project is shown in image 1. As we can see, the output is very descriptive and human-readable. This result will be explained by following some naming conventions for our methods and classes, which will be explained in detail below. First, let’s discuss what we can see in our test scenario. We defined five preconditions:

  1. The configuration for the SMPT server is readable
  2. The SMTP server is available
  3. The mail has a recipient
  4. The mail has attachments
  5. The mail is full composed

If all these conditions are true, the action will send a single e-mail got performed. Afterward, after the SMTP server is checked, we see that the mail has arrived. For the SMTP service, we use the small Java library greenmail [3] to emulate an SMTP server. Now it is understandable why it is advantageous for acceptance tests if they are written by other people. This increases the quality as early on conceptional inconsistencies appear. Because as long as the tester with the available implementations cannot map the required scenario, the requirement is not fully implemented.

Producing Descriptive Scenarios

Now is the a good time to dive deeper into the implementation details of our send e-mail test scenario. Our object under test is the class MailClientService. The corresponding test class is  MailClientScenarioTest, defined in the test packages. The scenario class definition is shown in listing 3.

@RunWith(JUnitPlatform.class)
public class MailClientScenarioTest
       extends ScenarioTest<MailServiceGiven, MailServiceAction, MailServiceOutcome> { 
    // do something 
}
Java

Listing 3: Acceptance Test Scenario for JGiven.

As we can see, we execute the test framework with JUnit5. In the  ScenarioTest, we can see the three classes: Given, Action, and Outcome in a special naming convention. It is also possible to reuse already defined classes, but be careful with such practices. This can cost some side effects. Before we now implement the test method, we need to define the execution steps. The procedure for the three classes are equivalent.

@RunWith(JUnitPlatform.class)
public class MailServiceGiven 
       extends Stage<MailServiceGiven> { 

    public MailServiceGiven email_has_recipient(MailClient client) {
        try { 
            assertEquals(1, client.getRecipentList().size());
        } catch (Exception ex) {
            System.err.println(ex.getMessage);
        }
        return self(); 
    } 
} 

@RunWith(JUnitPlatform.class)
public class MailServiceAction
       extends Stage<MailServiceAction> { 

    public MailServiceAction send_email(MailClient client) {
        MailClientService service = new MailClientService();
        try {
            assertEquals(1, client.getRecipentList().size());
            service.sendEmail(client);
        } catch (Exception ex) { 
            System.err.println(ex.getMessage);
        }
        return self();
    }
}

@RunWith(JUnitPlatform.class)
public class MailServiceOutcome 
       extends Stage<MailServiceOutcome> {

    public MailServiceOutcome email_is_arrived(MimeMessage msg) { 
         try {
             Address adr = msg.getAllRecipients()[0];
             assertEquals("JGiven Test E-Mail", msg.getSubject());
             assertEquals("noreply@sample.org", msg.getSender().toString());
             assertEquals("otto@sample.org", adr.toString());
             assertNotNull(msg.getSize());
         } catch (Exception ex) {
             System.err.println(ex.getMessage);
         }
         return self();
    }
}
Java

Listing 4: Implementing the AAA Principle for Behavioral Driven Development.

Now, we completed the cycle and we can see how the test steps got stuck together. JGiven supports a bigger vocabulary to fit more necessities. To explore the full possibilities, please consult the documentation.

Lessons Learned

In this short workshop, we passed all the important details to start with automated acceptance tests. Besides JGiven exist other frameworks, like Concordion or FitNesse fighting for usage. Our choice for JGiven was its helpful documentation, simple integration into Maven builds and JUnit tests, and the descriptive human-readable reports.

As negative point, which could people keep away from JGiven, could be the detail that you need to describe the tests in the Java programming language. That means the test engineer needs to be able to develop in Java, if they want to use JGiven. Besides this small detail, our experience with JGiven is absolutely positive.

A briefly overview to Java frameworks

When you have a look at Merriam Webster about the word framework you find the...

Working with JSON in Java RESTful Services using Jackson

Since a long time the Java Script Object Notation become as a lightweight standard...

Date vs. Boolean

Modeling database tables can quickly lead to redundancies that can easily be avoided. An example...

Treasure chest – Part 1

Through the years, different techniques to storage configuration settings for applications got established. We can...

Preventing SQL Injections in Java with JPA and Hibernate

Preventing SQL Injections in Java using SQL Parameters with the Java Persistence API (JPA) and...