Tag Archives: Spring Boot - Page 2

Gradle: Integration/GUI test setup example with Spring and Protractor

Setting upp integration tests that depends on background process can be a challenge in Gradle. Here is one solution that I have used:

gradle.build

apply plugin: 'java'

/**
* Handle of the background process (script scope)
*/
Process backendProcess

/**
* Task to start the Spring server
*/
task beforeE2eTests {
  ProcessBuilder builder
  builder = new ProcessBuilder('./gradlew bootRun'.split(' '))
  builder.redirectErrorStream(true)

  doLast {
    println "Starting backend"
    backendProcess = builder.start()

    InputStream sto = backendProcess.getInputStream()
    BufferedReader redr = new BufferedReader(new InputStreamReader(sto))

    /**
    * To prevent Gradle to go to next task before the server has started 
    * we add a loop that finds a specific log line. When that 
    * line appears we are good to go to next task
    */
    def line
    while ((line = redr.readLine()) != null) {
      println line
      if (line.contains("Started WebApplication")) {
        println "Backend is ready"
        break;
      }
    }
  }

  finalizedBy 'afterE2eTests'
}

/**
* Task to stop the Spring server
*/
task afterE2eTests {
  doLast {
    println "Stopping backend"
    backendProcess.destroy()
  }

  mustRunAfter 'testAngularE2e'
}

/**
* Task to start E2E tests
*/
task testAngularE2e(type: Exec) {
  mustRunAfter 'beforeE2eTests'

  /**
  * Run the Protractor tests
  */
  commandLine 'node_modules/.bin/protractor', 'e2e/protractor.conf.js'
}

/**
* Main testing task
*/
testAll {
  dependsOn beforeE2eTests, testAngularE2e
}

Tested on OSX 10.15.0 and Gradle 4.10.2

Using a different Bean depending on profile in Spring Boot

This is something that can be very useful when running your application in different environments. One case is that you want to place messages on a queue but you do not have access to the queue manager in the development environment. Here is an example of what a solution might be to that problem:

First, we create an interface that can act as a facade for our “send” method

public interface Gateway {
  void send(Message message);
}

Now we need to add this interface to our class

public class MQGateway implements Gateway {
  @Override
  void send(Message message){
    /* All the logic needed to send a message */
  }
}

And now we create two Beans. One for each profile

@Bean
@Profile("dev")
public MQGateway mqgatewayDevelop() {
  return new MQGateway() {
    @Override
    void send(Message message) {
      log.info("Mocked gateway. Sending message to log: " + message);
    }
  }
}

@Bean
@Profile("prod")
public MQGateway mqgatewayProduction() {
  return new MQGateway();
}

I usually put Bean creation in a configuration class so that any setting from application.yml is close at hand

And now we are going to use some “magic” to make Spring choose the right one

public class MyClass {
  @Autowire
  private Gateway mqGateway;

  public void myFunction(Message message) {
    mqGateway.send(message);
  }
}

So, how does this work. Well, by using the interface when calling the ‘send’ method we are forcing Sprint to find a suitable Bean of that type and since there only will be one active per profile Spring will find the right one.
If Spring can’t find a suitable Bean it will throw a exception

Tested on Spring Boot v2.2.4

Mock a dependency in system under test in a Spring Boot application with Mockito

System under test class example:

import my.special.sclient
...

class App {
  Sclient sclient = getNewSclient();
  
  public String methodA(String input) { 
    return sclient.getValue(input);
  }

  protected Sclient getNewSclient() {
    return new Sclient();
  }
}

Test class example:

import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
...

class Test {
  @Spy
  @InjectMocks
  private App sut;

  @Mock
  Sclient mockClient;

  @BeforeMethod
  public void setUp() {
    MockitoAnnotations.initMocks(this);
    when(sut.getNewSclient()).thenReturn(mockClient);
    when(mockClient.getValue("bar")).thenReturn("foo");
  }

  @Test
  public void myTest() {
    String value = sut.getValue("bar");
    assertThat(value, is("foo"));
  }
}

So, how does this work? I will try to explain below:

1. First we need to be able to intercept the ‘sclient’ in the App class. This is done by simply creating a ‘getNewSclient()’ function and then mock it in the Test class so that we instead can use a mocked version of it.

2. Next we need to setup our test class. Here we need both a @Spy and @InjectMocks on the App object. We also need a mocked instance of the ‘sclient’ we are going to use

3. Now we need to set upp the desired behaviour of our mocked ‘sclient’. We set it so that if you input “bar” you should get “foo” back

4. Done!

Tested on Java v1.8.0_252, Mockito v3.3.3, TestNG v6.11 and Spring Boot v2.2.4