Monday, November 20, 2017

Solving SLF4J: Class path contains multiple SLF4J bindings.

Problem:
While running unit tests, if you ever find these warnings, logged with INFO...

SLF4J: Class path contains multiple SLF4J bindings.
[INFO] SLF4J: Found binding in [jar:file:/C:/apache-maven-3.3.3/mvn.release.repo/org/slf4j/slf4j-log4j12/1.7.2/slf4j-log4j12-1.7.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
[INFO] SLF4J: Found binding in [jar:file:/C:/apache-maven-3.3.3/mvn.release.repo/org/slf4j/slf4j-nop/1.7.2/slf4j-nop-1.7.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
[INFO] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
[INFO] SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]

The solution for fixing this is....
Use the maven surefire plugin to exclude the org.slf4j:slf4j-log4j12 usage during tests (slf4j-nop-1.7.2 is only used during tests)

pom.xml extract:

<build>
  <plugins>
      <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <configuration>
              <classpathDependencyExcludes>
                 <classpathDependencyExcludes> org.slf4j:slf4j-log4j12 </classpathDependencyExcludes>
              </classpathDependencyExcludes>
   </configuration>
        </plugin>
    </plugins>
</build>
<dependencies>    <dependency>         <groupId>org.slf4j</groupId>         <artifactId>slf4j-api</artifactId>     </dependency>     <dependency>         <groupId>org.slf4j</groupId>         <artifactId>slf4j-nop</artifactId>         <version>1.7.2</version>         <scope>test</scope>     </dependency>   <dependency>

Friday, November 17, 2017

Java Unit Test Frameworks

I love writting unit tests for my code. It makes it easy to test code that is very hard to test in a running system, just for checking the behavior of certain implementations. Besides that, is useful when trying to refactor some code, so we can assure that the behavior is not broken.
Well, I'll show you the java unit test frameworks that I currently use...

Junit



The JUnit Platform serves as a foundation for launching testing frameworks on the JVM
JUnit 5 user guide is available as documentation.

Nice features:
Parameterized tests make it possible to run a test multiple times with different arguments.
Supports annotations.

E.g.
import org.junit.*;

public class TestXXX {
    @BeforeClass
    public static void setUpClass() throws Exception {
        // Code executed before the first test method
    }

    @Before
    public void setUp() throws Exception {
        // Code executed before each test
    }
    @Test
    public void testOneThing() {
        // Code that tests one thing
    }
    @After
    public void tearDown() throws Exception {
        // Code executed after each test 
    }
 
    @AfterClass
    public static void tearDownClass() throws Exception {
        // Code executed after the last test method 
    }
}

EasyMock



EasyMock provides dynamically generated Mock objects (at runtime), without having to implement them.
Can be used in conjunction with Junit.

E.g.
public class XXXTest extends TestCase {

    public void tesComputeValue(){
        ClassUnderTest testObject = new ClassUnderTest();
        ClassToMock mock = EasyMock.createMock(ClassToMock.class);
        EasyMock.expect(mock.getSomething()).andReturn("Hello");
        EasyMock.replay(mock);
        assertEquals("Hello", testObject.saySomething(mock));
    }
}

PowerMock


PowerMock is an extension to both Mockito and EasyMock that allows mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and more.
Allows the usage of the beneficts of PowerMock and the usage of Mockito to setup and verify expectations by using PowerMockito.

E.g.
@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassUnderTest.class)
public class XXXTest {
 
  private ClassToMock mock;
  private ClassUnderTest testObject;

  @Test
  public void tesComputeValue() {
    mock = PowerMockito.mock(ClassToMock.class);
    PowerMockito.when(mock.getSomething()).thenReturn("Hello");
    testObject = new ClassUnderTest(mockUserService);
    assertEquals("Hello", testObject.saySomething());
  }
}

Mockito


Mockito allows to verify the behavior of the system under test without establishing expectations beforehand, attempting to eliminate the expect-run-verify pattern, so the coupling is minimized.
Can be used in conjunction with Junit.

E.g.
public class XXXTest {
   
  private ClassToMock mock;
  private ClassUnderTest testObject;
   
   @Before
   public void setUp() {
      mock = mock(ClassToMock.class);
      testObject = new ClassUnderTest(mock);
   }
   
   @Test
   public void testComputeValue() throws Exception {
      when(mock.getSomething(any(String.class))).thenReturn("Hello");
      testObject.saySomething();
      verify(mock).getSomething(any(String.class));
   }
}

Nice features:
Can define the behavior of the same method call to produce different results, in the same test.

More...

More java unit tests frameworks can be found in this wikipedia listing.