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>
Related
Actually, it will be more complex question.
I want use AspectJ only in test purpose.
Have found suggestion to use if() JointPoint and some static boolean field.
Also, first I start using aspect as inner static class of my base test method.
After some experiments I replaced it to own class, but actually don’t got the result, that I want.
So, I just create some test project.
Maven 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>org.example</groupId>
<artifactId>Testing</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<mockito.version>3.11.2</mockito.version>
<aspectj.version>1.9.7</aspectj.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-surefire-provider
-->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<!--<configuration>
<argLine>-javaagent:${user.home}/.m2/repository/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar</argLine>
</configuration>-->
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14.0</version>
<configuration>
<complianceLevel>${maven.compiler.source}</complianceLevel>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Classes:
A:
package classes;
public class A {
private String a = "classes.A";
public String getA()
{
return a;
}
public String getFromB()
{
return new B().getB();
}
}
B:
package classes;
public class B {
private String b = "classes.B";
public String getB() {
return b;
}
}
test class:
package aspectj;
import classes.A;
import classes.B;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NewTest {
private static boolean useAspect = false;
public static boolean isUseAspect() {
return useAspect;
}
#BeforeEach
void init()
{
useAspect = true;
}
#Test
public void changeValue()
{
B b = new B();
System.out.println(b.getB());
}
#Test
public void changeValueInA()
{
A a = new A();
System.out.println(a.getFromB());
}
}
Aspect class
package aspectj;
import org.aspectj.lang.Aspects;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class AspectB {
#Pointcut("if()")
public static boolean useAspect()
{
return NewTest.isUseAspect();
}
#Pointcut("call(* classes.B.getB())")
public void callTestMethod() {}
#Around("callTestMethod()")
public String myAdvice(ProceedingJoinPoint point) throws Throwable {
return "You have been hacked!";
}
}
Main class:
package classes;
public class TestOutputHere {
public static void main(String[] args) {
System.out.println(new A().getFromB());
}
}
And I got result after running test and main method:
changeValue() -> You have been hacked!
changeValueInA() -> classes.B
main(String[] args) -> classes.B
Second result dont feet for me... So after some experiments and removing test scope for AspectJ dependencies, removing if() JointPoint (we can't use test classes from src) and placing Aspect class in src I got the result:
changeValue() -> You have been hacked!
changeValueInA() -> You have been hacked!
main(String[] args) -> You have been hacked!
Lust result dont feet to me too. And I really don’t want to use aspect for all project.
After that I just tried to use some Load-Time weaving with configuration for maven surefire plugin:
<configuration>
<argLine>
-javaagent:${user.home}/.m2/repository/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
</argLine>
</configuration>
And I got result, that I want:
changeValue() -> You have been hacked!
changeValueInA() -> You have been hacked!
main(String[] args) -> classes.B
So, where the question after thousands of these letters?)
Questions are:
Can I get this result with compile weaving and without using AspectJ
classLoader?
As I have performance restrictions in real project - how can AspectJ
classLoader affect performance of non-test environment in this case?
In case of load-time weaving that I describe - all classes of the
project will recompile by AspectJ? Only test? How recompiling work in load-time?
I will greatfull for this answers!
You have several problems in your code:
You set useAspect = true before each test, but never reset to false after a test ends. This would bleed context out into other tests where you want the aspect inactive. You should clean that up.
The aspect has an if() pointcut depending on a static method in a test class. The test class is unavailable during application runtime under normal circumstances. The static field and its accessor methods (if any) should be in the aspect class itself.
package aspectj;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class AspectB {
private static boolean useAspect = false;
public static void setUseAspect(boolean useAspect) {
AspectB.useAspect = useAspect;
}
#Pointcut("call(* classes.B.getB()) && if()")
public static boolean callTestMethod() {
return useAspect;
}
#Around("callTestMethod()")
public String myAdvice(ProceedingJoinPoint point) throws Throwable {
return "You have been hacked!";
}
}
package aspectj;
import classes.A;
import classes.B;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NewTest {
#BeforeEach
void init() {
AspectB.setUseAspect(true);
}
#AfterEach
void cleanUp() {
AspectB.setUseAspect(false);
}
#Test
public void changeValue() {
B b = new B();
System.out.println(b.getB());
}
#Test
public void changeValueInA() {
A a = new A();
System.out.println(a.getFromB());
}
}
Probably, your aspect is defined in src/test/java instead of src/main/java, which explains why it is only compiled into test classes and not into application classes. But the latter is what you expect, if a method call from one application class to another should be intercepted. Therefore, you need to move the aspect to the main sources and make aspectjrt have a compile scope, not a test scope.
But in this case where the aspect is supposed to only affect tests, I would recommend to not use compile-time weaving (CTW), because it would mean that the application always needs the AspectJ runtime on its class path (see above), even if the aspect is inactive. CTW only makes sense if at least sometimes during application runtime the aspect is meant to be active, too. Even then, it is debatable if load-time weaving (LTW) might not be the better solution, e.g. if it is a rarely used debugging aspect. CTW is ideal for production aspects. In this case, it seems to be fairly clear that LTW using the Java agent is the right approach. Like you said, you do not even need the ugly static field and the if() pointcut.
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.
I'm new to Spring. I'm trying to use ComponentScan.I have a simple bean with a string variable annotated with #Component. Trying to use the #Configuration with a java class instead of xml file. When I try to access the bean from my main class, it says 'No bean found'
project directory structure
StudentTest.java
package com.spring.Annotations.tests;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
#Component
public class StudentTest {
#Value("${name}")
private String name;
public String getName() {
return name;
}
public void setName(
String name) {
this.name = name;
}
public StudentTest()
{
System.out.println("obj created");
}
}
Config.java
package com.spring.Annotations.tests;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
#Configuration
#PropertySource("classpath=com.spring.Annoations.tests.project.properties")
#ComponentScan(basePackages={"com.spring.Annotations","com.spring.Annotations.tests"})
public class Config {
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
return configurer;
}
}
App.java
package com.spring.Annotations;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.spring.Annotations.tests.StudentTest;
public class App
{
public static void main( String[] args )
{
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext("com.spring.Annotations.tests.Config.class");
StudentTest s=(StudentTest)ctx.getBean("studentTest");
System.out.println( s.getName() );
}
}
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.spring</groupId>
<artifactId>Annotations</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Annotations</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.0.6.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
project.properties
name=Madhu
When I run App.java class it gives me following error.
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'studentTest' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:641)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1157)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:280)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:973)
at com.spring.Annotations.App.main(App.java:17)
use context:component-scan and context:annotation-configinto ApplicationContaxt.xml file. you can find the sample code :
<context:component-scan annotation-config="true" base-package="com.demo.test" />
<context:annotation-config />
component-scan is use for scanning all packages to scan.
Why do yo add "class" to the path? Try
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.spring");
You can only use this type of configuration if your spring version is greater than Spring 3.1.
Can you please check and comment your spring version.
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(com.spring.Annotations.tests.Config.class);
Remove double quotes inside AnnotationConfigApplicationContext and try
I am trying to implement AOP concept using Spring Boot. But before annotation is not working.
This is my code,
POM.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Application.properties
server.port=6500
spring.aop.proxy-target-class=true
Main:
package com.techno.theater;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.techno.theater.services.SampleService;
#SpringBootApplication
public class DigitalTheaterApplication {
private static Logger logger=LoggerFactory.getLogger(DigitalTheaterApplication.class);
public static void main(String[] args) {
SpringApplication.run(DigitalTheaterApplication.class, args);
new SampleService().sample();
}
}
Sample Service:
package com.techno.theater.services;
import org.springframework.stereotype.Service;
#Service
public class SampleService {
public void sample(){
System.out.println("Sample method inovking");
}
}
Aspect class
package com.techno.theater.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class AspectService {
#Before("execution(* com.techno.theater.services.SampleService.sample())")
public void beforeSampleMethod() {
System.out.println("Sample method aspect");
}
}
Here I am invoking sample method from DigitalTheaterApplication class but before execute this method my aspect method should be executed but it's not working am not sure do I need to add some configuration.
public static void main(String[] args) {
SpringApplication.run(DigitalTheaterApplication.class, args);
new SampleService().sample();
}
The code above is the problem, to be precise the new SampleService().sample(); is what is flawed in your code. You are creating a new instance outside the scope of Spring and as such it will not be exposed to AOP.
Instead what you should do, is retrieve the SampleService from the ApplicationContext.
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(DigitalTheaterApplication.class, args);
ctx.getBean(SampleService.class).sample();
}
This will get the Spring created, and proxied, instance, with AOP applied.
Another way, without messing around with the ApplicationContext is to create a CommandLineRunner which will be executed during startup.
public static void main(String[] args) {
SpringApplication.run(DigitalTheaterApplication.class, args);
}
#Bean
public CommandLineRunner tester(SampleService service) {
return args -> service.sample();
}
Something like that will also invoke the sample method on the Spring managed instance without having to get it yourself.
error: "package org.springframework.extensions.webscripts does not exist" for all the below imports
code:
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
public class Test1 extends AbstractWebScript{
public void execute(WebScriptRequest req, WebScriptResponse res){
String name = "World from Java";
}
}
You're missing the relevant classes in your classpath. If you're using maven, add the following to your pom:
<dependency>
<groupId>org.springframework.extensions.surf</groupId>
<artifactId>spring-webscripts</artifactId>
<version>1.2.0</version>
</dependency>