Generation mocks automatically works only in Spring projects?

Hi, I’m testing the ability of Diffblue to generate bean mocks automatically, however in the tests I did, I was only able to generate tests in classes annotated with Sprint stereotypes (Service, Controller, Componet…).

Diffblue is unable to automatically generate mocks from classes that use CDI - Contexts and Dependency Injection (Java EE)?

I also tested the commercial version (30-day trial) using EJB and was also unsuccessful.

Is it possible to generate mocks automatically without using Spring? If so, could you send an example? If not, is there a prevision that it will be added to Diffblue?

Additional Information:
OS: Windows 10 Enterprise, 64bit
Java: jdk1.8.0_291
Java version: 1.8
IntelliJ IDE 2021.1 with Diffblue Community Edition plugin / IntelliJ IDE 2021.1 with Diffblue 2021.05.01-commercial.2021.1
JUnit 4.12
Mockito 1.9.5

Example successful!!

@Component //Spring
public class MyBusiness {

	@Autowired //Spring
	private MyExternalAdapter adapter;

	public void testBusinessAdapter(String cabinet) throws Exception {
		adapter.executeExternalService(cabinet);
	}
}

Example 2 successful!!

@Component //Spring
public class MyBusiness {

	@Inject //CDI JavaEE
	private MyExternalAdapter adapter;

	public void testBusinessAdapter(String cabinet) throws Exception {
		adapter.executeExternalService(cabinet);
	}
}

Example 3 unsuccessful!!

@Named("MY_BUSINESS") //CDI JavaEE
public class MyBusiness {

	@Inject //CDI JavaEE
	private MyExternalAdapter adapter;

	public void testBusinessAdapter(String cabinet) throws Exception {
		adapter.executeExternalService(cabinet);
	}
}

Example 4 unsuccessful!!

@Stateless //EJB JavaEE
public class MyBusiness {

	@EJB //EJB JavaEE
	private MyExternalAdapter adapter;

	public void testBusinessAdapter(String cabinet) throws Exception {
		adapter.executeExternalService(cabinet);
	}
}

Example 5 unsuccessful!!

@Stateless //EJB JavaEE
public class MyBusiness {

	@Inject //CDI JavaEE
	private MyExternalAdapter adapter;

	public void testBusinessAdapter(String cabinet) throws Exception {
		adapter.executeExternalService(cabinet);
	}
}

Cover doesn’t explicitly support CDI at the moment, and so doesn’t understand how to populate @Inject annotated fields using field or setter injection.

If you’re able to rework your code to use constructor injection, then the class can be treated as a POJO and Cover will use Mockito to construct it and write tests:

@Named(“MY_BUSINESS”) //CDI JavaEE
public class MyBusiness {
  private MyExternalAdapter adapter;
  @Inject //CDI JavaEE
  public MyBusiness(MyExternalAdapter adapter) {
    this.adapter = adapter;
  }
  public void testBusinessAdapter(String cabinet) throws Exception {
    adapter.executeExternalService(cabinet);
  }
}

For example I got the following test generated:

public class MyBusinessTest {
  @Test
  public void testTestBusinessAdapter() throws Exception {
    // Arrange
    MyExternalAdapter myExternalAdapter = mock(MyExternalAdapter.class);
    doNothing().when(myExternalAdapter).executeExternalService(anyString());
    // Act
    (new MyBusiness(myExternalAdapter)).testBusinessAdapter(“Cabinet”);
    // Assert
    verify(myExternalAdapter).executeExternalService(anyString());
  }
}

Thanks @roxspring

Hi @jeansantolin, we are looking further into CDI support, is this something used across your applications - or do you use a mix of frameworks? I would like to understand the priority of this for you moving forward

Thanks for your time, it is really valuable to help me understand our users’ priorities

Matthew @ Diffblue

Thanks @roxsrping.

I modified my test to constructor injection according to the example provided, Cover was able to generate the test class, but it did not generate automatic mocks equal the example.

Is it possible to send a zip with the example working? Because I couldn’t identify what I may be doing wrong.

Test class generated:

public class MyBusinessTest {
    @Test
    public void testConstructor() {
        // TODO: This test is incomplete.
        //   Reason: Nothing to assert: the constructed class does not have observers (e.g. getters or public fields).
        //   Add observers (e.g. getters or public fields) to the class.
        //   See https://diff.blue/R002

        new MyBusiness(new MyExternalAdapter());
    }

    @Test
    public void testTestBusinessAdapter() throws Exception {
        // TODO: This test is incomplete.
        //   Reason: No meaningful assertions found.
        //   To help Diffblue Cover to find assertions, please add getters to the
        //   class under test that return fields written by the method under test.
        //   See https://diff.blue/R004

        (new MyBusiness(new MyExternalAdapter())).testBusinessAdapter("Cabinet");
    }
}

Hi @Matt,

The CDI is used in 90% of our projects and the default method used is field injection, not constructor injection.

For our scenario, it is not a valid alternative to change all systems to use constructor injection.