<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>testing &#8211; CodePills.com</title>
	<atom:link href="https://codepills.com/tag/testing/feed/" rel="self" type="application/rss+xml" />
	<link>https://codepills.com</link>
	<description>Helping you make a better code</description>
	<lastBuildDate>Sun, 18 Feb 2024 09:01:54 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>How to make multipart requests with file and object through autogenerated code defined in OpenAPI</title>
		<link>https://codepills.com/how-to-make-multipart-requests-with-file-and-object-through-autogenerated-code-defined-in-openapi/</link>
					<comments>https://codepills.com/how-to-make-multipart-requests-with-file-and-object-through-autogenerated-code-defined-in-openapi/#respond</comments>
		
		<dc:creator><![CDATA[Andrej Buday]]></dc:creator>
		<pubDate>Sat, 03 Feb 2024 18:08:37 +0000</pubDate>
				<category><![CDATA[Solutions]]></category>
		<category><![CDATA[Converter]]></category>
		<category><![CDATA[Deserialization]]></category>
		<category><![CDATA[Endpoint Creation]]></category>
		<category><![CDATA[File Upload]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Multipart Form Data]]></category>
		<category><![CDATA[MultipartFile]]></category>
		<category><![CDATA[Object Validation]]></category>
		<category><![CDATA[ObjectMapper]]></category>
		<category><![CDATA[OpenAPI]]></category>
		<category><![CDATA[Postman]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[Validator]]></category>
		<guid isPermaLink="false">https://codepills.com/?p=1364</guid>

					<description><![CDATA[This article explains how to create a Spring Boot endpoint using OpenAPI to receive objects and, optionally, files through multipart form data, focusing on deserialization and validation of incoming objects. <a href="https://codepills.com/how-to-make-multipart-requests-with-file-and-object-through-autogenerated-code-defined-in-openapi/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>This article explains creating a Spring Boot endpoint using OpenAPI to receive objects and, optionally, files through multipart form data, focusing on deserialization and validation of incoming objects.</p>
<p><span id="more-1364"></span></p>
<h2>Introduction</h2>
<p>In this article we will continue and spin from the <a href="https://codepills.com/how-to-make-multipart-requests-with-files-through-autogenerated-code-defined-in-openapi/" title="How to make multipart requests with files through autogenerated code defined in OpenAPI" target="_blank" rel="nofollow noopener">previous article</a> about generating OpenAPI with Spring Boot for multipart endpoint and uploading files through it. We strongly recommend reading the last article if you want to import more than one file. But in this article, we will focus only on the optional import of a single file.</p>
<p>But instead of multiple files, we will try to upload only one file and one serialized object, for example, the information about the new user.</p>
<p>We will also show how to handle the deserialization of the incoming object from the string at the Spring Boot backend and how to control proper deconstruction if some fields are optional or not mandatory.</p>
<h2>OpenAPI User import definition YAML</h2>
<p>So we start where we end the last time. Let&#8217;s generate the Spring Boot endpoint through the OpenAPI schema, which will be able to receive objects and, optionally, a file through multipart form data.</p>
<pre><code class="language-yaml">openapi: 3.0.2
info:
  title: User management module
  description: User management
  version: '0.1'
  contact:
  email: optional@email.com
servers:
  - url: https://localhost:8080/api/user-management

paths:
  /users/import:
    post:
      summary: Create new Users with optional attachment
      tags:
        - users
      operationId: createUserWithOptionalFile
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                createUser:
                  description: Wrapper containing information for new user creation
                  type: object
                  properties:
                    username:
                      description: Users username
                      type: string
                    age:
                      description: Users password
                      type: number
                    creationTimestamp:
                      description: Time when the user will be defined as created in the system
                      type: string
                      format: date-time
                      example: "2024-02-29T12:30:00.000Z"
                    email:
                      description: Email of the user
                      type: string
                    addressId:
                      description: ID of the users address
                      type: string
                    accessRights:
                      description: List of access rights for the user
                      type: array
                      items:
                        type: object
                        properties:
                          accessRightId:
                            description: ID of the access right
                            type: string
                          note:
                            description: Note for the access right
                            type: string
                  required:
                    - username
                    - email
                    - accessRights
                optionalFile:
                  description: Optional file attachment
                  type: string
                  format: binary
              required:
              - createUser
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateUserResponse'
        '400':
          description: Bad Request</code></pre>
<p>As you can see, we have defined the endpoint /users/import, which will be able to receive the object createUser and optionally also a single file. The createUser object is defined in the schema and is required, while the file is optional. CreateUser object also has various definitions of fields, although unimportant and displayed only for current examples.</p>
<p>You can refer to the object schema to make the YAML file more readable and concise. The object&#8217;s schema can be defined in self-standing section dedicated to components.</p>
<pre><code class="language-yaml">openapi: 3.0.2
info:
  title: User management module
  description: User management
  version: '0.1'
  contact:
  email: optional@email.com
servers:
  - url: https://localhost:8080/api/user-management

paths:
  /users/import:
    post:
      summary: Create new Users with optional attachment
      tags:
        - users
      operationId: createUserWithOptionalFile
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                createUser:
                  $ref: '#/components/schemas/CreateUser'
                optionalFile:
                  description: Optional file attachment
                  type: string
                  format: binary
              required:
              - createUser
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateUserResponse'
        '400':
          description: Bad Request

components:
  schemas:
    CreateUser:
      description: Wrapper containing information for new user creation
      type: object
      properties:
        username:
          description: Users username
          type: string
        age:
          description: Users password
          type: number
        creationTimestamp:
          description: Time when the user will be defined as created in the system
          type: string
          format: date-time
          example: "2024-02-29T12:30:00.000Z"
        email:
          description: Email of the user
          type: string
        addressId:
          description: ID of the users address
          type: string
        accessRights:
          description: List of access rights for the user
          type: array
          items:
            type: object
            properties:
              accessRightId:
                description: ID of the access right
                type: string
              note:
                description: Note for the access right
                type: string
      required:
        - username
        - email
        - accessRights</code></pre>
<h2>Enforcing and casting mandatory properties of multipart request</h2>
<p>Multipart file can accept only the <i>String</i>s or <i>File</i>s (better visible in <a href="#testing_with_postman">testing with Postman</a> section). So any string input &#8211; Java&#8217;s serialized object, or JSON, is at the end nothing more than just a string of bytes.</p>
<p>The problem will arise during the deserialization of autogenerated code. It does not matter if you declare the object cast as required. With proper mapping, the input will be taken as a String and not as the type you want to use from the method signature.</p>
<p>Mapper and validator factory beans can solve the issue and handle the input.</p>
<p>First, register one new bean for object Validation. Optionally, you can register the ObjectMapper with JavaTimeModule to handle the date-time format, as we will use the date-time string in ISO format (&#8220;YYYY-MM-DDTHH:MM:SS.mmmZ&#8221;). The Validator is created through LocalValidatorFactoryBean.</p>
<pre><code class="language-java">import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import jakarta.validation.Validator;
import lombok.val;

@Configuration
public class AppConfig {

  //@Bean
  //public ObjectMapper objectMapper() {
  //  val objectMapper = new ObjectMapper();
  //  objectMapper.registerModule(new JavaTimeModule());
  //  return objectMapper;
  //}

  @Bean
  public Validator validator() {
    return new LocalValidatorFactoryBean();
  }

}</code></pre>
<p>The code was written for Java 21 dependencies with Lombok.</p>
<p>To enforce the proper conversion, you must create a new Spring component to convert the incoming string to the object. The component will be able to handle the deserialization and validation of the object.</p>
<pre><code class="language-java">import java.util.Set;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Validator;
import lombok.val;

@Component
public class StringToCreateUserDtoConverter implements Converter&lt;String, CreateUserDto> {

  private final Validator validator;
  private final ObjectMapper objectMapper;

  public StringToCreateUserDtoConverter(final Validator validator, final ObjectMapper objectMapper) {
    this.validator = validator;
    this.objectMapper = objectMapper;
  }

  @Override
  public CreateUserDto convert(final String source) {
    CreateUserDto createUserDto;
    try {
        createUserDto = objectMapper.readValue(source, CreateUserDto.class);
    } catch (JsonProcessingException e) {
        throw new CreateUserDeserializationException("Input mapping and processing error: " + e.getMessage());
    }
    val violations = validator.validate(createUserDto);
    if (!violations.isEmpty()) {
        throw new ConstraintViolationException(violations);
    }
    return createUserDto;
  }

}</code></pre>
<p>Just for the record, I will also add here the custom exception you can throw and catch in the custom exception handler:</p>
<pre><code class="language-java">import java.io.Serial;

import lombok.Getter;

@Getter
public class CreateUserDeserializationException extends RuntimeException {

  @Serial
  private static final long serialVersionUID = 1659771269447893294L;

  public CreateUserDeserializationException(String msg) {
    super(msg);
  }

}</code></pre>
<h2>Unit tests</h2>
<p>I recommend writing the unit tests for the converter. It is a good practice to test the conversion and validation of the object. As we rely heavily upon Spring magic, a lot can unintentionally influence the component&#8217;s behaviour without us discovering it.</p>
<p>The code below is just an example of the unit tests with the usage of <i>SpringBootTest</i> and <i>LocalTestcontainers</i> which ties to get close to real-world use scenarios. We highly recommend to accommodate tests to your environment and needs.</p>
<pre><code class="language-java">
import org.testcontainers.containers.PostgreSQLContainer;

public class LocalTestcontainers {

    public static void startPostgres(){
        PostgreSQLContainer<?> postgre = new PostgreSQLContainer<>("postgres:16.0")
            .withDatabaseName("INSERT_DATABASE_NAME")
            .withUsername("INSERT_DATABASE_USERNAME")
            .withPassword("INSERT_DATABASE_PASSWORD");
        postgre.start();

        System.setProperty("spring.datasource.url", postgre.getJdbcUrl());
        System.setProperty("spring.datasource.username", postgre.getUsername());
        System.setProperty("spring.datasource.password", postgre.getPassword());
    }

}</code></pre>
<pre><code class="language-java">import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.testcontainers.junit.jupiter.Testcontainers;

import com.codepills.usermanagementmodule.api.exception.CreateUserDeserializationException;
import com.codepills.usermanagementmodule.utils.LocalTestcontainers;

import jakarta.validation.ConstraintViolationException;
import lombok.val;

@SpringBootTest
@Testcontainers
class StringToCreateUserDtoConverterTest {

    static {
        LocalTestcontainers.startPostgres();
    }

    @Autowired
    private StringToCreateUserDtoConverter stringToCreateUserDtoConverter;

    @Test
    void testConvertValidInputString() {
        // Arrange
        val username = "JohnDoe";
        val age = 25;
        val formatter = DateTimeFormatter.ISO_INSTANT;
        val now4CreationTime = Instant.now();
        val email = "john.doe@noemail.com";
        val addressId = UUID.randomUUID();
        val accessRightId1 = UUID.randomUUID();
        val accessRightId2 = UUID.randomUUID();

        val stringBuilder = new StringBuilder();
        stringBuilder.append("{");
        stringBuilder.append("\"username\" : \"").append(username).append("\",");
        stringBuilder.append("\"age\" : ").append(age).append(",");
        stringBuilder.append("\"creationTimestamp\" : \"").append(formatter.format(now4CreationTime)).append("\",");
        stringBuilder.append("\"email\" : \"").append(email).append("\",");
        stringBuilder.append("\"addressId\" : \"").append(addressId).append("\",");
        stringBuilder.append("\"accessRights\" : [");
        stringBuilder.append("{");
        stringBuilder.append("\"accessRightId\" : \"").append(accessRightId1).append("\",");
        stringBuilder.append("}, {");
        stringBuilder.append("\"accessRightId\" : \"").append(accessRightId2).append("\"");
        stringBuilder.append("}]}");
        val validInput = stringBuilder.toString();

        // Act
        val createUserDto = stringToCreatUserDtoConverter.convert(validInput);

        // Assert
        assertNotNull(createUserDto);
        assertEquals(username, createUserDto.getUsername());
        assertEquals(age, createUserDto.getAge());
        assertEquals(now4CreationTime, createUserDto.getCreationTimestamp());
        assertEquals(email, createUserDto.getEmail());
        assertEquals(addressId.toString(), createUserDto.getAddressId());
        assertEquals(2, createUserDto.getAccessRights().size());
        assertEquals(accessRightId1.toString(), createUserDto.getAccessRights().get(0).getAccessRightId());
        assertEquals(accessRightId2.toString(), createUserDto.getAccessRights().get(1).getAccessRightId());
    }

    @Test
    void testConvertInvalidInputString() {
        // Arrange
        val invalidInput = "invalid input string";
        // Act & Assert
        try {
            stringToCreateUserDtoConverter.convert(invalidInput);
        } catch (CreateUserDeserializationException ex) {
            assertEquals("Input mapping and processing error: Unrecognized token 'invalid': was expecting (JSON String, Number, Array, "
                             + "Object or token 'null', 'true' or 'false')\n at [Source: (String)\"invalid input string\"; line: 1, "
                             + "column: 8]", ex.getMessage());
        }
    }

    @Test
    void testConvertInputWithValidationErrors() {
        // Arrange
        val username = "JohnDoe";
        val age = 25;
        val formatter = DateTimeFormatter.ISO_INSTANT;
        val now4CreationTime = Instant.now();
        val email = "john.doe@noemail.com";
        val addressId = UUID.randomUUID();
        val accessRightId1 = UUID.randomUUID();
        val accessRightId2 = UUID.randomUUID();

        val stringBuilder = new StringBuilder();
        stringBuilder.append("{");
        stringBuilder.append("\"username\" : \"").append(username).append("\",");
        stringBuilder.append("\"age\" : ").append(age).append(",");
        stringBuilder.append("\"creationTimestamp\" : \"").append(formatter.format(now4CreationTime)).append("\",");
        stringBuilder.append("\"email\" : \"").append(email).append("\",");
        // Missing addressId
        stringBuilder.append("\"addressId\" : null,");
        stringBuilder.append("\"accessRights\" : [");
        stringBuilder.append("{");
        stringBuilder.append("\"accessRightId\" : \"").append(accessRightId1).append("\",");
        stringBuilder.append("}, {");
        stringBuilder.append("\"accessRightId\" : \"").append(accessRightId2).append("\"");
        stringBuilder.append("}]}");
        val validInput = stringBuilder.toString();

        // Act & Assert
        try {
            stringToCreateUserDtoConverter.convert(inputWithValidationErrors);
        } catch (ConstraintViolationException ex) {
            assertEquals(1, ex.getConstraintViolations().size());
        }
    }

}</code></pre>
<h2>User Management Controller</h2>
<p>Now, all we need to do is create a controller to implement the OpenAPI schema.</p>
<p>Here is an example of the controller:</p>
<pre><code class="language-java">@Logger
@RestController
@RequiredArgsConstructor
public class UserManagementController implements UserManagementApi {

  @Override
  public ResponseEntity&lt;Void&gt&gt; createUserWithOptionalFile(
        @RequestPart(name = "createUser") final CreateUserDto createUserDto,
        @RequestPart(name = "optionalFile", required = false) MultipartFile optionalFile
     ) {
    if (optionalFile == null || optionalFile.isEmpty()) {
        log.info("No optionalFile uploaded.");
    } else {
        log.info("PDF optionalFile {} uploaded but not saved.", optionalFile.getOriginalFilename());
    }

    // You can work with createUserDto here

    return ResponseEntity.ok().build();
  }

}</code></pre>
<p>I will leave the implementation of <em>createUserWithOptionalFile()</em> method up to you as it is not the main focus of this article.</p>
<p>Again, notice the <i>optionalFile</i> and <i>createUser</i> keywords in the method arguments. It is the same as the keyword as defined in the OpenAPI schema.</p>
<h2 id="testing_with_postman">Testing with Postman</h2>
<p>Nothing blocks our development anymore, and we can start testing the endpoint with Postman. The endpoint will be able to receive the serialized object in the form of string and also the file. However, attaching the file to the request is, of course, optional.</p>
<p>As it might need to be stressed more, the most important thing is using the exact keywords defined in the OpenAPI schema. In our case, for importing object, it will be <i>createUser</i> and for optional file, it will be <i>optionalFile</i>.</p>
<p>Let&#8217;s run the SpringBoot app at localhost.</p>
<p>Backend should be running at localhost. And if added the necessary logic for file processing into the controller, we should be able to upload serialized objects in JSON format and optional file through the <em>/users/import</em> endpoint.</p>
<p>When using Postman, you also need to define the type of multipart key. It is either the <em>String</em> or <em>File</em>. For files, use <em>File</em>, and for the object, use <em>String</em>. Do not forget that in the <a href="https://codepills.com/how-to-make-multipart-requests-with-files-through-autogenerated-code-defined-in-openapi/" title="How to make multipart requests with files through autogenerated code defined in OpenAPI" target="_blank" rel="nofollow noopener">previous article</a> we discuss the implementation of sending multiple files through multipart request.</p>
<p>All you need to do is to define your endpoint <code>POST</code> request in Postman. Select <code>POST</code> request, add the URL, and in the body tab, select form-data and add the keywords <em>createUser</em> set as <em>String</em> and <em>optionalFile</em> as <em>File</em> .</p>
<p><img fetchpriority="high" decoding="async" src="https://codepills.com/wp-content/uploads/2024/02/postman_multipart_request_with_multiple_objects_and_files.png" alt="Postman multipart request with multiple objects and files" width="665" height="316" class="size-full wp-image-1373" srcset="https://codepills.com/wp-content/uploads/2024/02/postman_multipart_request_with_multiple_objects_and_files.png 665w, https://codepills.com/wp-content/uploads/2024/02/postman_multipart_request_with_multiple_objects_and_files-300x143.png 300w" sizes="(max-width: 665px) 100vw, 665px" /></p>
<p>The most important part is to really define serialized object as <em>String</em> and not <em>File</em>.</p>
<p>Here is an example of <em>createUser</em> as <em>String</em>:</p>
<pre><code class="language-text">{
	"username" : "johndoe",
	"age" : "25",
	"creationTimestamp" : "2024-02-29T12:30:00.000Z",
	"email" : "john.doe@noemail.com",
	"addressId" : "f8935f28-8d7b-40a4-96d7-a3288976617e",
	"accessRights" : [
		{
      "accessRightId" : "712d5a0a-11b5-4a44-9e92-6e67d16be2aa"
    }
	]
}</code></pre>
<h2>Conclusion</h2>
<p>This article has shown how to create a Spring Boot endpoint to receive objects and, optionally, file through multipart form data. We have also demonstrated how to handle the deserialization of the incoming object from the string at the Spring Boot backend and how to control proper deconstruction if some fields are optional or not mandatory.</p>
<p>Is it applicable to auto-generating infrastructure code through OpenAPI with Spring Boot for multipart endpoint and uploading files? Let us know in the comments below. Do you have your trick or see another way <u>how to enforce and deserialize multipart object</u>? Let us know in the comments below the article. We would like to hear your ideas and stories.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://codepills.com/how-to-make-multipart-requests-with-file-and-object-through-autogenerated-code-defined-in-openapi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Verify method was called n-times with Mockito</title>
		<link>https://codepills.com/verify-method-was-called-n-times-with-mockito/</link>
					<comments>https://codepills.com/verify-method-was-called-n-times-with-mockito/#respond</comments>
		
		<dc:creator><![CDATA[Andrej Buday]]></dc:creator>
		<pubDate>Sat, 03 Apr 2021 15:31:10 +0000</pubDate>
				<category><![CDATA[Testing]]></category>
		<category><![CDATA[dependency injection]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[mockito]]></category>
		<category><![CDATA[testing]]></category>
		<guid isPermaLink="false">https://codepills.com/?p=1206</guid>

					<description><![CDATA[Mockito Verify example for n-times calls using various verification modes. <a href="https://codepills.com/verify-method-was-called-n-times-with-mockito/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>This short article will explain how to <strong>verify</strong> that Mock&#8217; method was called n-times with the help of <strong>Mockito testing framework</strong>.</p>
<p><span id="more-1206"></span></p>
<h2>Introduction</h2>
<p>We often encounter the problem during testing that we do not care about the data correctness, as much as we care about correct algorithm flow. In this situations, we want to check if specific methods were hit and executed. Sometimes we need to go deeper and seek an answer on how often these methods were called or verify that the methods called at all.</p>
<p>The necessary method, which will help us in our testing quest, is called <a href="https://javadoc.io/static/org.mockito/mockito-core/3.9.0/org/mockito/Mockito.html#exact_verification" title="Mockito verify" target="_blank" rel="nofollow noopener">verify()</a> and is part of <strong>Mockito testing framework</strong>.</p>
<h2>Mockito verify verification options</h2>
<pre><code class="language-java">public static <T> T verify(T mock, VerificationMode mode)</code></pre>
<p><i>mock</i> is object of type <code>T</code> you are placing into the <code>verify()</code> method for verification. As a second method argument is <code>VerificationMode</code> <i>mode</i> variable, which describes how the <i>mock</i> should be verified. Possible verification modes are:</p>
<pre><code class="language-java">verify(mock, times(5)).someMethod("was called exactly five times");
verify(mock, never()).someMethod("was never called");
verify(mock, atLeast(5)).someMethod("was called at least five times");
verify(mock, atLeastOnce()).someMethod("was called at least once");
verify(mock, atMost(5)).someMethod("was called at most five times");</code></pre>
<p>There is also one special <code>VerificationMode</code> mode called <code>only()</code>. This mode verifies that no other method was called on the mock so far.</p>
<pre><code class="language-java">verify(mock, only()).someMethod("only someMethod was called");</code></pre>
<h2>Mockito verify verification modes in action </h2>
<p>In order to test individual verification modes, we will write a simple test. For testing purposes it will consist from two classes. (Both are inner private classes for <i>MockitoVerifyTest.java</i>.) First will be a fake class <code>Account</code> which trough dependency injection will use second class <code>Counter</code>. <code>Counter</code> class will be used as a <code>Mock</code> in our test.</p>
<p>Here is a <code>Counter</code> class:</p>
<pre><code class="language-java">private class Counter {

    private int counter;

    public Counter() {
        this.counter = 0;
    }

    public void increment() {
        this.counter++;
    }

    public void reset() {
        this.counter = 0;
    }

    public int getCount() {
        return this.counter;
    }
}</code></pre>
<p>And here is the <code>Account</code> class:</p>
<pre><code class="language-java">private class Account {

    private Counter counter;

    public Account(Counter counter) {
        this.counter = counter;
    }

    public void incrementCounter() {
        this.counter.increment();
    }

    public void resetCounter() {
        this.counter.reset();
    }

    public int getCounterValue() {
        return this.counter.getCount();
    }
}</code></pre>
<p>And finally, here is an exemplary test where you can see usage of individual verification modes:</p>
<pre><code class="language-java">import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@RunWith(MockitoJUnitRunner.class)
public class MockitoVerifyTest {

    @Mock
    Counter counter;

    @Test
    public void testMockitoVerifyMethodCalls() {

        Account account = new Account(counter);

        // Verification using only() and atLeastOnce()
        account.incrementCounter();
        Mockito.verify(counter, only()).increment();
        Mockito.verify(counter, atLeastOnce()).increment();

        // Verification using times(X)
        for (int i = 0; i < 4; i++) {
            account.incrementCounter();
        }
        Mockito.verify(counter, times(5)).increment();

        // Verification using atLeast(X), atMost(X), never()
        for (int i = 0; i < 5; i++) {
            account.incrementCounter();
        }
        Mockito.verify(counter, atLeast(5)).increment();
        Mockito.verify(counter, atMost(10)).increment();
        Mockito.verify(counter, never()).getCount();
    }
}</code></pre>
<p>Let's discuss little but example code.</p>
<pre><code class="language-java">Account account = new Account(counter);

// Verification using only() and atLeastOnce()
account.incrementCounter();
Mockito.verify(counter, only()).increment();
Mockito.verify(counter, atLeastOnce()).increment();</code></pre>
<p>First, we will create new instance of <code>Account</code> class which trough dependency injection is injected with Mock instance of our <code>Counter</code> class.</p>
<p>As first we verify that there was no method, except <i>increment()</i> method, has been called on our mock at all. And as second verification, we will check that it was called at least once,</p>
<pre><code class="language-java">for (int i = 0; i < 4; i++) {
    account.incrementCounter();
}
Mockito.verify(counter, times(5)).increment();</code></pre>
<p>Now we call <i>incrementCounter()</i> method four more times, remember we already called it once, and we will check that it was mock method injected to instance was called <b>exactly</b> five times.</p>
<pre><code class="language-java">for (int i = 0; i < 5; i++) {
    account.incrementCounter();
}
Mockito.verify(counter, atLeast(5)).increment();
Mockito.verify(counter, atMost(10)).increment();
Mockito.verify(counter, never()).getCount();</code></pre>
<p>In the last section, we are incrementing the counter again five more times, and now we are checking if it was called <b>at least</b> five times and <b>at most</b> ten times.</p>
<p>On the last line we are checking method call for Mock' <i>getCount()</i> method that was <b>never</b> called.</p>
<h2>Conclusion</h2>
<p>This article contains a straightforward test on which we have demonstrated how to use Mockito <code>verify</code> method for mock' method call verification.</p>
<p>As always, you can find all our examples on our <a href="https://github.com/codekopf/tutorials-jvm/tree/master/testing-modules/mockito/" title="Tutorial JVM - Testing modules - Mockito" target="_blank" rel="nofollow noopener">GitHub project</a>!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://codepills.com/verify-method-was-called-n-times-with-mockito/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to check if two lists are equal in Java</title>
		<link>https://codepills.com/how-to-check-if-two-lists-are-equal-in-java/</link>
					<comments>https://codepills.com/how-to-check-if-two-lists-are-equal-in-java/#respond</comments>
		
		<dc:creator><![CDATA[Andrej Buday]]></dc:creator>
		<pubDate>Thu, 01 Apr 2021 09:55:26 +0000</pubDate>
				<category><![CDATA[Testing]]></category>
		<category><![CDATA[assert list]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java Collections]]></category>
		<category><![CDATA[Java List]]></category>
		<category><![CDATA[testing]]></category>
		<guid isPermaLink="false">https://codepills.com/?p=1202</guid>

					<description><![CDATA[A short article focused on a widespread problem in testing if two list instances are identical, or rather say if they contain the same elements in the same order. <a href="https://codepills.com/how-to-check-if-two-lists-are-equal-in-java/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>This short article will explain to you what List equality means and how to compare two <strong>Java lists</strong> against each other.</p>
<p><span id="more-1202"></span></p>
<h2>Introduction</h2>
<p>Checking list equality is a widespread problem; we often need to compare the list elements against each other. Comparison and assertion occur many times during the testing when we need to assert results with predefined expectations.</p>
<h2>Two lists equality</h2>
<p>At first, some might think, that for equality of two lists is conditioned by lists containing the same elements. This way of thinking is not entirely true. Single look into the Java documentations for <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html#equals-java.lang.Object-" title="List equals" target="_blank" rel="nofollow noopener">List.equals()</a> method will uncover us true meaning of list equality:</p>
<blockquote><p>
    &#8230; two lists are defined to be equal if they contain the same elements in the same order.
</p></blockquote>
<p>Therefore, we need to compare the lists&#8217; elements mutually, but we also need to check the order of the elements in the lists reciprocally.</p>
<p>So first, let&#8217;s take a good look at how not to do a list equality check.</p>
<h2>Compare two list with the bruteforce</h2>
<p>Following lines of code are placed here only for demonstration purposes. For all cost, you must avoid such hideous brute force solution in your code.</p>
<pre><code class="language-java">private boolean compareLists(final List list1,final List list2) {
    if(list1.size() == list2.size()) {
        if(list1.isEmpty() && list2.isEmpty()) {
            return true;
        }
        for(int i = 0; i < list1.size(); i++) {
            if(!list1.get(i).equals(list2.get(i))) {
                return false;
            };
        }
        return true;
    }
    return false;
}</code></pre>
<p>The reason why to not use it in your code is that this code is basically <code>List</code> interface implementation of the <code>equal()</code> method. Therefore all you need to use for comparing two lists is to call <code>equal()</code> method.</p>
<pre><code class="language-java">private boolean compareLists(final List list1,final List list2) {
    return list1.equals(list2);
}</code></pre>
<p><b>Interface method definition ensures</b> that the equals method works through different implementations of the <strong>List</strong> interface in a same way.</p>
<h2>Framework usage</h2>
<p>For testing purposes, it is probably better to use some of the available <strong>Java frameworks for testing</strong>, which can give us more options in List testing.</p>
<p>In our examples, we will play with the following code snippet based on user entities belonging to different groups. We will compare lists are figure out if all users are members of all groups.</p>
<pre><code class="language-java">List<String> users = Arrays.asList("John Doe", "Tom Smith", "Paul Iron", "George Silver");
List<String> moderators = Arrays.asList("John Doe", "Tom Smith", "Paul Iron", "George Silver");
List<String> admins = Arrays.asList("John Doe", "Tom Smith", "Paul Iron", "George Silver");</code></pre>
<h3>JUnit</h3>
<p>Rather than using and printing equals for tests, it is better to use assert methods. <strong>JUnit</strong> testing framework offers us three suitable ways for list equality assertion.</p>
<ul>
<li><code>assertEquals(expected, actual)</code> - Asserts that two objects are equal. If they are not, an <code>AssertionError</code> without a message is thrown. If <i>expected</i> and <i>actual</i> are <code>null</code>, they are considered equal.</li>
<li><code>assertNotSame(unexpected, actual)</code> - Asserts that two objects do not refer to the same object. If they do refer to the same object, an <code>AssertionError</code> without a message is thrown.</li>
<li><code>assertNotEquals(unexpected, actual)</code> - Asserts that two objects are not equals. If they are, an <code>AssertionError</code> without a message is thrown. If <i>unexpected</i> and <i>actual</i> are <code>null</code>, they are considered equal.</li>
</ul>
<pre><code class="language-java">@Test
public void testJUnitListAsserts() throws Exception {
    Assert.assertEquals(users, moderators);
    Assert.assertNotSame(users, moderators);
    Assert.assertNotEquals(users, admins);
}</code></pre>
<h2>Conclusion</h2>
<p>This article has shown you how not to do list assertion and explain how to check and assert two lists equality.</p>
<p>As always, you can find all our examples on our <a href="https://github.com/codekopf/tutorials-jvm/tree/master/testing-modules/junit-basics/" title="Tutorial JVM - Testing Modules - JUnit Basics" target="_blank" rel="nofollow noopener">GitHub project</a>!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://codepills.com/how-to-check-if-two-lists-are-equal-in-java/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to load files from Spring JUnit test resources folder</title>
		<link>https://codepills.com/how-to-load-files-from-spring-junit-test-resources-folder/</link>
					<comments>https://codepills.com/how-to-load-files-from-spring-junit-test-resources-folder/#respond</comments>
		
		<dc:creator><![CDATA[Andrej Buday]]></dc:creator>
		<pubDate>Wed, 03 Mar 2021 10:04:00 +0000</pubDate>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[ClassLoader]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java 7]]></category>
		<category><![CDATA[JUnit]]></category>
		<category><![CDATA[legacy project]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[testing]]></category>
		<guid isPermaLink="false">https://codepills.com/?p=1141</guid>

					<description><![CDATA[In this short tutorial, you will see how to read the files from the <i>/src/test/resources</i> test directory path in your Spring application. <a href="https://codepills.com/how-to-load-files-from-spring-junit-test-resources-folder/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>In this short tutorial we will show you how to read the files from the <i>/src/test/resources</i> directory path.</p>
<p><span id="more-1141"></span></p>
<p>It is common practice for unit testing in the Spring JUnit test to load files and their content to make more robust test cases. Or we have a test case where we need perhaps read or write data or test specific files in general.</p>
<h2>1. Using ClassLoader</h2>
<p>First option is to use and instance of the <code>ClassLoader</code>.</p>
<pre><code class="language-java">final ClassLoader classLoader = getClass().getClassLoader();
final String resourceName = "daily_report.csv";
final File file = new File(classLoader.getResource(resourceName).getFile());
final String absolutePath = file.getAbsolutePath();

System.out.println(absolutePath);

Assert.assertTrue(absolutePath.endsWith("/daily_report.csv"));</code></pre>
<p>We will get the output of the absolute path as:</p>
<pre><code class="language-bash">/Users/your.user.name/DEV/tutorials/testing-modules/junit-5-basics/target/test-classes/daily_report.csv</code></pre>
<p>Be aware that the path to the resource will look slightly different from the rest of the examples. It is because the ClassLoader looks for the resources on the classpath. Therefore obtaining a path to the resource is from the point of the compiled project.</p>
<p>If you build your project with Maven, compiled classes and resources are in the <code>/target</code> directory in the project root folder. That is why you need to count on the path to resource adjusted for the difference. The other two methods use project root.</p>
<h2>2. Using Path</h2>
<p>Second option is to use an instance of the <code>Path</code> class. We will call a static factory method <code>Paths.get()</code> which will return us its new instance. Then we will convert <code>Path</code> to <code>File</code> instance and from the that we will extract absolute path with <code>getAbsolutePath()</code> method.</p>
<pre><code class="language-java">final Path resourcePath = Paths.get("src","test","resources");
final String absolutePath = resourcePath.toFile().getAbsolutePath();

System.out.println(absolutePath);

Assert.assertTrue(absolutePath.endsWith("src/test/resources"));</code></pre>
<p>We will get the same output as in example using <code>java.io.File</code>:</p>
<pre><code class="language-bash">/Users/your.user.name/DEV/tutorials/testing-modules/junit-5-basics/src/test/resources</code></pre>
<p><i>Path</i> class was introduced in Java 7; consequently, it is available also in older and legacy projects.</p>
<h2>3. Using java.io.File</h2>
<p>Third approach is to use an instance of the <code>java.io.File</code> class to read the <i>/src/test/resources</i> directory. We will create instance and then we will call its method <code>getAbsolutePath()</code> method. Path we will obtain in this way is relative path towards the current working directory of the project.</p>
<pre><code class="language-java">final String resourcePath = "src/test/resources";
final File file = new File(resourcePath);
final String absolutePath = file.getAbsolutePath();

System.out.println(absolutePath);

Assert.assertTrue(absolutePath.endsWith("src/test/resources"));</code></pre>
<p>Let&#8217;s see an example output when running on the Unix based system:</p>
<pre><code class="language-bash">/Users/your.user.name/DEV/tutorials/testing-modules/junit-5-basics/src/test/resources</code></pre>
<h2>Conclusion</h2>
<p>This article was a quick tutorial where we showed how to read resources from the <i>/src/test/resources</i> directory in JUnit 5.</p>
<p>There are three different ways how to get a resource for testing. We can either use File, Paths or ClassLoader class.</p>
<p>As always, you can find all our examples on our <a href="https://github.com/codekopf/tutorials-jvm/tree/master/testing-modules" title="Tutorial JVM - Testing modules" target="_blank" rel="nofollow noopener">GitHub project</a>!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://codepills.com/how-to-load-files-from-spring-junit-test-resources-folder/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How To Start With Codeception PHP Framework And Selenium</title>
		<link>https://codepills.com/how-to-start-with-codeception-php-framework-and-selenium/</link>
					<comments>https://codepills.com/how-to-start-with-codeception-php-framework-and-selenium/#respond</comments>
		
		<dc:creator><![CDATA[Andrej Buday]]></dc:creator>
		<pubDate>Wed, 09 Nov 2016 20:12:29 +0000</pubDate>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Composer]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP framework]]></category>
		<category><![CDATA[Selenium]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[UAT]]></category>
		<category><![CDATA[webdriver]]></category>
		<guid isPermaLink="false">http://codekopf.com/?p=625</guid>

					<description><![CDATA[This is a small guide explaining how to start with Codeception PHP test framework and how to integrate it with Selenium for automated tests. <a href="https://codepills.com/how-to-start-with-codeception-php-framework-and-selenium/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p>Recently I have been working on one job interview with test case requiring to write portion of automatized tests in Codeception PHP framework. Since I didn&#8217;t have any experience with Codeception PHP framework I needed to learn quickly as much as I could.</p>
<p><span id="more-625"></span></p>
<p>This is a small guide explaining how to start with Codeception PHP test framework and how to integrate it with Selenium for automated tests.</p>
<h2>What is Codeception and what is good for?</h2>
<p><a href="http://codeception.com/" target="_blank">Codeception</a> is PHP framework devoted to test PHP code. Installation is very simple and requires only a few steps. It is actually well known for its easy code readability of test units. Codeception PHP framework is used for acceptance testing. Codeception emphasize usage of the variable name $I, so than many lines of code are very descriptive exp. $I want to do this and that, $I expect to see something. etc.</p>
<p>Codeception helps with creating test suites for 3 types of testing:</p>
<ul>
<li>Accaptance</li>
<li>Unit</li>
<li>Functional</li>
</ul>
<h3><strong>What is acceptance testing?</strong></h3>
<p>Acceptance tests are emulating behavior of a real user visiting website.</p>
<blockquote><p>Acceptance testing is formal testing with respect to user needs, requirements, and business processes conducted to determine whether a system satisfies the acceptance criteria and to enable the user, customers or other authorized entity to determine whether or not to accept the system. Acceptance testing is also known as user acceptance testing (UAT), end-user testing, operational acceptance testing or field (acceptance) testing.</p>
<p>Source: Wikipedia</p></blockquote>
<p>First of all I have to recommend to watch first video by Jeffrey Way from EnvatoTuts+ for Codeception series <a title="Modern Testing in PHP with Codeception at EnvatoTuts+" href="https://code.tutsplus.com/courses/modern-testing-in-php-with-codeception" target="_blank" rel="nofollow">Modern Testing in PHP with Codeception</a>. Although the first video is very well narrated and instructive for beginner, rest of the serie is not and I would not recommend to pay for premium account to watch the rest. Jeffrey expect knowledge of many related topics where you can use Codeception (DB connection, Laravel, &#8230;) but do not create simple code snippets for your first test and does not talk much about usage of elemental Codeception functions. Serie is aimed for advanced users.</p>
<h2>1. Download</h2>
<p>You can download Codeception framework out of the box via composer by CLI command <code>$ composer require "codeception/codeception"</code> .</p>
<p>You can also implement it into already existing project updating a composer.json file placing following:</p>
<pre class="lang:js decode:true">{
    "require": {
        "codeception/codeception": "^2.2",
        ...
    }
}
</pre>
<p>For newest version of Codeception please visit and search <a title="PHP packages" href="https://packagist.org/" target="_blank" rel="nofollow">packagist.org</a> . Over CLI just hit composer command in folder of your project: <code>composer update</code> (or <code>composer install)</code>.</p>
<h2>2. Create codeception.yml</h2>
<p>By executing <code>codecept bootstrap</code> Codeception creates the codeception.yml file and bunch of new files for test suites.</p>
<h3>What is test suite?</h3>
<blockquote><p>The test suite is a collection of test cases that are intended to be used to test a software program to show that it has some specified set of behaviours. A test suite often contains detailed instructions or goals for each collection of test cases and information on the system configuration to be used during testing. A group of test cases may also contain prerequisite states or steps, and descriptions of the following tests.</p>
<p>Collections of test cases are sometimes incorrectly termed a <span style="text-decoration: underline;">test plan</span>, a <span style="text-decoration: underline;">test script</span>, or even a <span style="text-decoration: underline;">test scenario</span>.</p>
<p style="text-align: left;">Source: <a href="https://en.wikipedia.org/wiki/Test_suite" target="_blank">Wikipedia</a></p>
</blockquote>
<h2>3. Create your first test</h2>
<p>Create your first test by Codeception command:</p>
<p><code>codecept generate:cept acceptance FirstTest</code></p>
<p>Note: Codeception scenario tests are called Cepts.</p>
<h2>4. Setting Acceptance test method</h2>
<p>Basically there are 2 method which I managed to try to in short time &#8211; PHP Browser and Selenium WebDriver:</p>
<ol style="list-style-type: upper-alpha;">
<li>PHP Browser &#8211; works on idea of web scrapper. Code does not emulate real browser but just download HTML code and apply test scenarios on it.</li>
<li><a href="http://www.seleniumhq.org/projects/webdriver/" target="_blank">Selenium WebDriver</a> &#8211; works as &#8220;artificial user&#8221;. PHP test case code emulate real browser and perform actions upon real website in browser.</li>
</ol>
<p>I would recommended to first start with PHP Browser and than try Selenium WebDriver. PHP Browser can check HTML page contents, click links, fill forms, and submit POST and GET requests. Unfortunately PHP Browser have few drawbacks (you can click only on links with valid urls or form submit buttons,  you can’t fill fields that are not inside a form, you can’t work with JavaScript interactions like modal windows or date-pickers) and for more complex tests is necessary to use Selenium WebDriver.</p>
<h3>4.1. PHP Browser</h3>
<p>For setting up PHP Browser just change acceptance.suite.yml to:</p>
<pre class="lang:yaml decode:true">class_name: AcceptanceTester
modules:
    enabled:
        - PhpBrowser:
            url: "http://localhost/app"          
        - \Helper\Acceptance</pre>
<h3>4.2. Selenium WebDriver</h3>
<p>For setting Selenium WebDriver you need to make 3 steps.</p>
<p>1) Change acceptance.suite.yml to:</p>
<pre class="lang:yaml decode:true">class_name: AcceptanceTester
modules:
    enabled:
        - WebDriver:
            url: "http://localhost:8000/app"
            browser: firefox            
        - \Helper\Acceptance</pre>
<p>2) In your .bash_profile you must also set GeckoDriver (drivers emulating Firefox) which you can download from <a href="https://github.com/mozilla/geckodriver/releases" target="_blank">mozilla/geckodriver</a> GitHub page.</p>
<pre class="lang:default decode:true">## Selenium GeckoDriver
export PATH=$PATH:/PATH_TO_GECKODRIVER_FOLDER/</pre>
<p>3) To set Selenium WebDriver is also necessary download <a href="http://www.seleniumhq.org/download/" target="_blank">Selenium Server</a> and run it prior the test. To run Selenium Server change directory to folder where is file located and type server run command <code>java -jar selenium-server-standalone-<em>YOUR.V.NO</em>.jar</code> .</p>
<h2>5 .Writing first PHP test</h2>
<p>Under acceptance folder we will create first test in FirstTest.php file. We will try to check &#8220;Hello World!&#8221; text at homepage:</p>
<pre class="lang:php decode:true">&lt;?php
  $I = new AcceptanceTester($scenario);
  $I-&gt;wantTo('Test Frontpage');
  $I-&gt;amOnPage('/');
  $I-&gt;see('Hello World!', 'h1');
?&gt;</pre>
<h2>6. Running the test</h2>
<p>Running the test case is possible by simple command <code>codecept run</code> . You will write this command often so you can create temporary (alias in your folder) or permanent alias (in .bash_profile) by creating alias exp. <code>alias runtest=vendor/bin/codecept run</code> and than just type your alias.</p>
<p>If you have done everything right, with Selenium you should new see Firefox window executing your first test. After finishing it, browser will close down and terminal shows announcement about Success. PHP Webdriver execute all test just over the terminal info panel.</p>
<h3>6.1 Further use</h3>
<p>To show the list of all available commands you need to type <code>vendor/bin/codecept</code> . It will also handy to create alias for it ( but just for <code>vendor/bin/ </code>and than type<code> codecept</code> ).</p>
<p>Codecept will always by run execute every single test you have wrote all together. It helps to nerrow down only the test suite which we want by selecting test suit in command: <code>codecept acceptance/functional/unit run</code> .</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://codepills.com/how-to-start-with-codeception-php-framework-and-selenium/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
