Category Archives: Java - Page 8

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

Debug SSL in Java

Certificates can be tricky to debug because they do not always give you a helpful error messages. To be able to turn the JVM debug mode on can be a great help. I will here show two methods to enable debug mode for SSL:

As an VM option

java -Djavax.net.debug=ssl:handshake myprogram

Or as a system property (in your code):

System.setProperty("javax.net.debug", "ssl:handshake");

Hope it will help you track down that nasty SSL bug 🙂

Tested on OSX 10.15.6, Java 1.8.0_252

SSLHandshakeException: unable to find valid certification path to requested target

You are trying to connect to a server over SSL and you get the following error:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:198)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1967)
...

This means that your computer does not trust the remote computer. The remote computer serves a certificate that your computer is unable to find a trusted source for. Could be that the remote certificate is selfsigned or uses a CA that you computer does not know

One solution: Add the remote computers certificate into your truststore:
1. Get the remote computer certificate using OpenSSL:

openssl s_client -connect <remote computer adress> <remote computer port>

This will present the remote computers certificate (BEGIN CERTIFICATE to END CERTIFICATE). Copy this to a file (Preserve BEGIN and END rows)
2. Add the remote certificate to your java truststore

sudo keytool -import -alias remote_computer_cert -file <remote computer cert> -keystore /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/cacerts

3. Done – connect again – the error should be gone

Tested on OSX v10.15.6, OpenSSL 2.8.3 (LibreSSL) and Java 1.8.0_252 (OpenJDK)