ArgumentCaptor and comparing with hasItems - java

i am already desperate, i cannot find out why this test is not evaluated as successful. I have checked it milion times:
package someptest;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
import java.sql.SQLException;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import somep.Order;
import somepBO.BOException;
import somepdao.OrderDAO;
public class XXX {
#Mock
OrderDAO dao;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void captor_A() throws SQLException, BOException {
Order order = new Order();
ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
when(dao.read(any(Integer.class))).thenReturn(order);
dao.read(123);
dao.read(456);
verify(dao, times(2)).read(intCaptor.capture());
#SuppressWarnings("unused")
List<Integer> xs = intCaptor.getAllValues();
assertThat(intCaptor.getAllValues(), hasItems(456));
}
}
Here is a screen from my debugging, captor catches correct values, but assertThat does not accept it, why?

Phew, something seems to go quite wrong on your machine. Based on your test, I created the following self-contained test class:
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.List;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
public class ArgumentCaptorTest {
private static class Order {
}
public static class OrderDAO {
public Order read(Integer any) {
return null;
}
}
#Mock
OrderDAO dao;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void captor_A() {
Order order = new Order();
ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
when(dao.read(any(Integer.class))).thenReturn(order);
dao.read(123);
dao.read(456);
verify(dao, times(2)).read(intCaptor.capture());
assertThat(intCaptor.getAllValues(), hasItems(456));
}
}
Used dependencies (pom.xml):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>testing</groupId>
<artifactId>testing</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.18.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
When I start the test, it runs perfectly and gives me a green bar. For what I see, you're doing it right. Maybe you have version conflicts between JUnit, Hamcrest and Mockito that lead to your error? I used these JAR versions:
junit:junit:4.12
org.hamcrest:hamcrest-core:1.3
org.mockito:mockito-core:2.18.3
I also left the imports so you can compare them with yours (just in case that a "wrong" import causes the error). As you statically import Matchers.* from the Hamcrest package, I am quite sure that this and/or your used library versions cause your problem.

Related

Aspect Method is not triggered

I'm trying to get my Aspect class to work but it gets completely ignored.
I have following files:
MyAnnotation.java
package annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MyAnnotation {
}
MyAspect.java
package annotations;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class MyAspect {
#Before("#annotation(annotations.MyAnnotation)*")
public void interceptMethods(final JoinPoint thisJoinPoint) {
System.out.println(thisJoinPoint);
}
}
MyClass.java
package annotations;
import org.springframework.stereotype.Service;
#Service
public class MyClass {
#MyAnnotation
public int myMethod(final int i) {
System.out.println("method: " + i);
return i;
}
}
MyRestController.java
package annotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MyRestController {
#Autowired
MyClass myClass;
#GetMapping("/myClass")
private int callMyMethod() {
return myClass.myMethod(1);
}
}
Application.java
package annotations;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>experiments</groupId>
<artifactId>annotations</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.2.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.11.RELEASE</version>
</dependency>
</dependencies>
</project>
Does anyone see the problem and how to fix it?
I've tried multiple Before expressions ("execution(* annotations..(..))") but I just can't see to get it working.
I've tried Around instead of Before.
I've tried Pointcuts with Before.
I've been through articles:
AspectJ #Before annotation issue
Spring AspectJ, pointcut before method execution where method OR class is annotated
I finally did it. I'll leave the solution here for other people in need for a basic example.
These are the files:
MyAnnotation.java
package annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MyAnnotation {
}
MyAspect.java - it's tricky because:
annotation #Aspect is not sufficient. The annotation #Component also needs to be added to aspect class. If annotation #Component is omitted, the application will ignore the class.
in #Before annotation, there needs to be "and args(*)". If the args are omitted, there will be null pointer exception.
Code:
package annotations;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class MyAspect {
#Before("execution(* annotations.*.*(..)) and args(*)")
public void beforeExecution(final JoinPoint joinPoint) {
System.out.println("5");
}
}
MyClass.java
package annotations;
import org.springframework.stereotype.Service;
#Service
public class MyClass {
#MyAnnotation
public int myMethod(final int i) {
System.out.println("method: " + i);
return i;
}
}
MyRestController
package annotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MyRestController {
#Autowired
MyClass myClass;
#GetMapping("/myClass")
private int callMyMethod() {
return myClass.myMethod(1);
}
}
Application.java
package annotations;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>experiments</groupId>
<artifactId>annotations</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.2.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.11.RELEASE</version>
</dependency>
</dependencies>

How to mock Spring's JdbcTemplate.queryForList using Mockito?

I want to know how to mock the particular code using Mockito:
List<Map<String, Object>> list = jdbcTemplate.queryForList(
sqlQuery,
new Object[] { inflowId }
);
I tried the following code:
Mockito.doReturn(list)
.when(jdbcTemplate)
.queryForList(Mockito.anyString(), Mockito.any(Class.class));
and:
when(
jdbcTemplate.queryForList(Mockito.anyString(), Mockito.any(Object[].class))
).thenReturn(list);
My problem is that particular method is not getting mocked in JUnit. When the method is called, it returns null whereas it should return the list.
This should work:
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class DemoTest {
#Test
public void mockJdbcTemplate() {
JdbcTemplate mockTemplate = Mockito.mock(JdbcTemplate.class);
List<Map<String, Object>> mockResult = new ArrayList<>();
Mockito.when(mockTemplate.queryForList(Mockito.anyString(), ArgumentMatchers.<Object>any())).thenReturn(mockResult);
// Alternatively:
// when(mockTemplate.queryForList(anyString(), Mockito.<Object>any())).thenReturn(mockResult);
String query = "some query";
Object[] params = new Object[]{1};
List<Map<String, Object>> returnedResult = mockTemplate.queryForList(query, params);
Assert.assertThat(returnedResult, CoreMatchers.sameInstance(mockResult));
}
}
The trick is to use ArgumentMatchers.<Object>any() as there are multiple queryForList method implementations and the one we want to mock receives a varargs parameter.
Following code i used with spring boot, mockito
/** class on which uni test is driven **/
public class Decompile {
#Autowired
private JdbcTemplate jdbcTemplate;
public List<Map<String, Object>> getRunner()
{
try{
return jdbcTemplate.queryForList("select * from users");
}
catch (Exception e) {
System.err.println(e);
}
return null;
}
}
Unit test case starts
/** Unit test case for above class **/
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.jdbc.core.JdbcTemplate;
#RunWith(MockitoJUnitRunner.class)
public class DecompileTest {
#Mock/* works fine with autowired dependency too */
JdbcTemplate jdbcTemplate;
#InjectMocks/* for the claa that we are mocking */
Decompile testclass;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testgetRunner() {
List<Map<String, Object>> expectedresultList = new ArrayList<>();
Mockito.lenient().when(jdbcTemplate.queryForList("select * from users.. ")).thenReturn(expectedresultList);
List<Map<String, Object>> response = testclass.getRunner();
}
}
mvn package used as following (compatible with spring version > 2)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

How to mock Injected value relying on a qualifier using JerseyTest

I'm trying to mock a controller/resource including the jax-rs layer. The class has dependencies that need to be injected.
It however also has some String values that are injected using a qualifier interface.
Basically, I'm using JerseyTest to run a single controller and use HK2 for dependency injection. I created a ResourceConfig and registered a AbstractBinder to bind the injected classes.
This works fine for regular injected dependencies, but when the the additional #SomeQualifierInterface annotation is added, it crashes with the following error:
MultiException stack 1 of 3
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=String,parent=ThingsController,qualifiers={#com.company.SomeQualifierInterface()},position=-1,optional=false,self=false,unqualified=null,10035302)
...
MultiException stack 2 of 3
java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.company.ThingsController errors were found
...
MultiException stack 3 of 3
java.lang.IllegalStateException: Unable to perform operation: resolve on com.company.ThingsController
...
See the simplified full code example below:
Controller / Resource
import org.slf4j.Logger;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
#Path("/things")
public class ThingsController {
#Inject
private Logger log;
#Inject
#SomeQualifierInterface
private String injectedQualifierValue;
#GET
public Response getThings() {
log.info("getting things");
System.out.println("Injected value: " + injectedQualifierValue);
return Response.status(200).entity("hello world!").build();
}
}
Qualifier interface
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
#Qualifier
#Retention(RUNTIME)
#Target({ TYPE, METHOD, FIELD, PARAMETER })
public #interface SomeQualifierInterface { }
Producing service
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
#ApplicationScoped
public class SomeProducerService {
#Produces
#Dependent
#SomeQualifierInterface
public String getQualifierValue() {
return "some value!";
}
}
Test
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import org.slf4j.Logger;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import static junit.framework.TestCase.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
public class MockedThingsControllerTest extends JerseyTest {
private Logger logMock = mock(Logger.class);
#Override
protected Application configure() {
ResourceConfig resourceConfig = new ResourceConfig(ThingsController.class);
resourceConfig.register(new AbstractBinder() {
#Override
protected void configure() {
bind(logMock).to(Logger.class);
bind("some mocked value").to(String.class); // Doesn't work
bind(new SomeProducerService()).to(SomeProducerService.class); // Doesn't work
}
});
return resourceConfig;
}
#Test
public void doSomething() {
Response response = target("/things").request().get();
assertEquals(200, response.getStatus());
verify(logMock).info("getting things");
}
}
POM
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.27.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.28</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.28</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.28</version>
<scope>test</scope>
</dependency>
Solved!
First, use the AbstractBinder from org.glassfish.hk2.utilities.binding.AbstractBinder instead of org.glassfish.jersey.internal.inject.AbstractBinder.
Second, create a class that extends AnnotationLiteral and implements the interface.
Last, bind the value to a TypeLiteral and set the qualifiedBy to the AnnotationLiteral.
Full code:
import org.glassfish.hk2.api.AnnotationLiteral;
import org.glassfish.hk2.api.TypeLiteral;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import org.slf4j.Logger;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import static junit.framework.TestCase.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
public class MockedThingsControllerTest extends JerseyTest {
private Logger logMock = mock(Logger.class);
#Override
protected Application configure() {
ResourceConfig resourceConfig = new ResourceConfig(ThingsController.class);
resourceConfig.register(new AbstractBinder() {
#Override
protected void configure() {
bind(logMock).to(Logger.class);
bind("some mocked value").to(new TypeLiteral<String>() {}).qualifiedBy(new SomeQualifierLiteral());
}
});
return resourceConfig;
}
#Test
public void doSomething() {
Response response = target("/things").request().get();
assertEquals(200, response.getStatus());
verify(logMock).info("getting things");
}
static class SomeQualifierLiteral extends AnnotationLiteral<SomeQualifierInterface> implements SomeQualifierInterface {}
}

TooLittleActualInvocations:

I try to use mock to verify method for serveral times.But I meet this problem.
org.mockito.exceptions.verification.TooLittleActualInvocations:
personDao.update(isA(com.zhaolu08.Person));
Wanted 3 times:
-> at com.zhaolu08.PersonServiceTest.testUpdate(PersonServiceTest.java:32)
But was 1 time:
while my code is:
package com.zhaolu08;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.isA;
import static org.mockito.Mockito.eq;
public class PersonServiceTest {
private PersonDao mockDao;
private PersonService personService;
#Before
public void setUp() throws Exception {
//模拟PersonDao对象
mockDao = mock(PersonDao.class);
when(mockDao.getPerson(1)).thenReturn(new Person(1, "Person1"));
when(mockDao.update(isA(Person.class))).thenReturn(true);
personService = new PersonService(mockDao);
}
#Test
public void testUpdate() throws Exception {
boolean result = personService.update(1, "new name");
Assert.assertTrue("must true", result);
verify(mockDao, times(2)).getPerson(eq(1));
verify(mockDao, times(3)).update(isA(Person.class));
}
}
I can't find out the problem. I try some methods. They did not work.
My IDE is idea.
Maven pom is:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
</dependency>
I can't find out why it doesn't work. It is just a simple demo. It's too wired.
It seems due to the fact that you are expecting personDao.update to be invoked 3 times and actually in your method personService.update(1, "new name"); it is getting invoked only 1 time

PowerMockito: InvalidUseOfMatchersException while mocking static method with string [] argument

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Misplaced argument matcher detected here:
I am facing the org.mockito.exceptions.misusing.InvalidUseOfMatchersException exception while doing powermockito on following static method.
public class ShellCommandUtil {
public static ArrayList executeShellCommand(String[] shellcmd) {
ArrayList output = new ArrayList();
//removed the actual logic of sending shellcommand to the system getting the result;
return output;
}
}
TestMethod written is defined below
#RunWith(PowerMockRunner.class)
#PrepareForTest(ShellCommandUtil.class)
public class ShellDataTest{
#Test
public void testExecuteShellCommand() {
ArrayList resultData = new ArrayList();
resultData.add("data1");
resultData.add("data2");
PowerMockito.mockStatic(ShellCommandUtil.class);
PowerMockito.when(ShellCommandUtil.executeShellCommand(Mockito.any(String [].class))).thenReturn(resultData);
}
}
Can you please help what is defined wrong here in this line
PowerMockito.when(ShellCommandUtil.executeShellCommand(Mockito.any(String[].class))).thenReturn(resultData);
In pom.xml, I have added the following dependency
<!-- https://mvnrepository.com/artifact/org.powermock/powermock-mockito-release-full -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-mockito-release-full</artifactId>
<version>1.6.4</version>
<type>pom</type>
</dependency>
Please let me know your thoughts in this problem.
Thanks,
Rajeswari
According to the PowerMockito class's Javadoc, you should have written
PowerMockito.when(ShellCommandUtil.class, "executeShellCommand", Mockito.any(String [].class)).thenReturn(resultData);
Tried creating a fresh project with following details, do confirm if this differs from your implementation except for class names. Since this works for me -
Base Class -
import java.util.ArrayList;
public class Shell {
public static ArrayList executeShellCommand(String[] shellcmd) {
ArrayList output = new ArrayList();
//removed the actual logic of sending shell command to the system getting the result;
return output;
}
}
Test Class -
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
#RunWith(PowerMockRunner.class)
#PrepareForTest(Shell.class)
public class ShellTest {
#Test
public void testExecuteShellCommand() {
ArrayList resultData = new ArrayList();
resultData.add("data1");
resultData.add("data2");
PowerMockito.mockStatic(Shell.class);
PowerMockito.when(Shell.executeShellCommand(Mockito.any(String[].class))).thenReturn(resultData);
System.out.println("All went fine.");
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>powermock-mockito</groupId>
<artifactId>mock</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.powermock/powermock-mockito-release-full -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-mockito-release-full</artifactId>
<version>1.6.4</version>
</dependency>
</dependencies>
</project>

Categories