Thursday, December 27, 2018

MavenLocal

Take this scenario.

You are writing a new application A
B is an existing application that needs to be integrated with A

Now A is not in production yet and definitely not uploaded to your firm's Maven repository.
Or you might want to see how A works with B. Some basic integration, that I, as A's developer, need to ensure.

What I need is, to publish A in a local repository from where B will read from.

A and B both are gradle projects.

From A :


    publishing {
        repositories {
            mavenLocal()
        }
       
        publications {
            mavenJava(MavenPublication) {
                from components.java
            }
        }
    }


This uploads A's artifacts to m2 repository

And at B:



repositories {
        maven {
            url 'http://mavenAtMyFirm'
        }
        // Added to look for dependent libraries in local maven repo. Helps in integration
        mavenLocal()
    }


mavenLocal will read dependencies from local m2 repository.


Java 8 : Collectors.toMap | Do you know that Values cannot be null?

In Java Map, you can have null key and null values as well.

But when you are using Collectors.toMap() be wary not to have a KeyMapper and ValueMapper that will give null keys or null values.

Internally it uses Map.merge which will throw NPE if key or value is null. This is an open bug at JDK


Reference :
https://stackoverflow.com/questions/24630963/java-8-nullpointerexception-in-collectors-tomap 

Saturday, February 10, 2018

Mockito : Argument Captor - catches reference and not value

This is the service to test :

public void method(List<String> inputs) {

   Map<String,Object> parameterMap = new HashMap<>();

   parameterMap.put("common_attr1","blah");
   parameterMap.put("common_attr2","blah");

   for(String input: inputs) {
       parameterMap.put("selector",input);
       dao.makeDBCall(parameterMap);
   }

}

To collect the argument passed to the DB call, you would ideally go for the ArgumentCaptor and see if each call is made with the corresponding input passed to the method()


But, this will not work because ArgumentCaptor gives you the reference. so all the captured value will point to the argument corresponding to the last call made to the DB call.

Solution :

Use thenAnswer to collect the parameters while invoking the DB call.

List<String> actualSelectorsPassedForInputs = new ArrayList<>();
when(dao.makeDBCall(anyObject())).thenAnswer(invocation->{
 Object[] args = invocation.getArguments();
 HashMap<String,Object> parameterMap = (HashMap<String,Object>) args[0];
 actualSelectorsPassedForInputs.add(parameterMap.get("selector"));
});

// do assertions on actualSelectorsPassedForInputs

Reference :
1) https://stackoverflow.com/questions/11984128/capturing-previous-values-to-verify-mock-object

Tuesday, October 17, 2017

Creating test jar in Maven

My project is moduled as common, server, web, dao

For test cases I am using Random beans

Since the model objects are used across all the modules, to have a randomizer setup for each of these module is duplication.

So I am adding this randomizer related classes and configuration only at common module, and referencing at other module for test scope

At common :
<project>

  ...

  <build>

    <plugins>

      ...

      <plugin>

        <groupId>org.apache.maven.plugins</groupId>

        <artifactId>maven-jar-plugin</artifactId>

        <version>3.0.2</version>

        <executions>

          <execution>

            <goals>

              <goal>test-jar</goal>

            </goals>

          </execution>

        </executions>

      </plugin>

      ...

    </plugins>

  </build>

  ...

</project>



At dao :
<project>
  ...
  <dependencies>
    <dependency>
      <groupId>com.foo</groupId>
      <artifactId>common</artifactId>
      <type>test-jar</type>
      <version>version</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  ...
</project>


You can read more about this here

If you are building your project with maven.test.skip=true this test-jar is not generated. To overcome this use profile activation. i.e. at dao, add test-jar dependency only if the maven.test.skip != true

<profiles>

     <profile>

         <activation>

            <property>

               <name>maven.test.skip</name>

               <value>!true</value>

            </property>

         </activation>

         <dependencies>

            <dependency>

             <groupId>com.foo</groupId>

        <artifactId>common</artifactId>
        <type>test-jar</type>
        <version>version</version>
        <scope>test</scope>
        </dependency>

         </dependencies>

      </profile>

    </profiles>

Tuesday, October 10, 2017

Log mybatis sql query

To log SQL queries from a specific mapper in mybatis, add the mapper namespace to the logger level.
Eg :
If this is the mapper file,
<mapper namespace="customer">
Then to log statements that are defined in this mapper xml,
<logger name="customer">
        <level value="trace"/>
        <appender-ref ref="consoleAppender" />
</logger>

Friday, October 6, 2017

Use of profiles in Spring

In this blog I would have detailed about creating a transaction proxy. Now lets say you need to hook this proxy only test cases.
i.e. stageUtils has to be stageUtilsProxy wherever it is used only for the test cases.

Here is where profile come into picture. You can read more about it here

Add a overridden-context-for-test-profile.xml with testcase profile
<?xml version="1.0" encoding="UTF-8"?>



<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

         http://www.springframework.org/schema/beans/spring-beans.xsd" profile="testcase">



     <bean id="testStageUtils" scope="prototype" class="com.foo.infra.util.StageUtils" />



    <bean id="stageUtils"

class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<property name="transactionManager" ref="transactionManager" />

<property name="target" ref="testStageUtils" />

<property name="transactionAttributes">

<props>

<prop key="*">PROPAGATION_REQUIRES_NEW</prop>

</props>

</property>

</bean>



</beans>


Add this xml to the test-application-context.xml
<?xml version="1.0" encoding="UTF-8"?>



<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:tx="http://www.springframework.org/schema/tx"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

         http://www.springframework.org/schema/beans/spring-beans.xsd

         http://www.springframework.org/schema/tx

         http://www.springframework.org/schema/tx/spring-tx.xsd">



    <import resource="classpath:application-context.xml"/>

    <import resource="classpath:overridden-context-for-test-profile.xml"/>

</beans>


Annotate your BaseIntegrationTest class with @ActiveProfile annotation

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {

        "classpath:test-application-context.xml"

        })

@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)

@Transactional

@ActiveProfiles(profiles="testcase")

public abstract class BaseIntegrationTest {

Friday, September 8, 2017

Adding maven dependencies from github

How to add dependencies from github into your maven project

https://jitpack.io/

Example :
If I have to add dependency from
https://github.com/cheekychinnu/PnlAggregator

Enter the repo as below and hit lookup



I know! So cool