I'm trying to get the number of times a private method has been called.
I can do this with mockito for public methods:
Mockito.verify(mockedObject, times(numberOfTimes)).methodToBeChecked();
Is there an equivalent for PowerMockito?
I dont want tu use spy.
Thanks in advance.
Yes, it is.
Here my dependencies:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.28.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
The class under test:
public class A {
private void _test(){
}
public void test(){
for (int i = 0; i < 10; i++) {
_test();
}
}
}
My Junit:
#RunWith(PowerMockRunner.class)
#PrepareForTest({A.class})
public class ATest {
private A a;
public ATest() {
}
#Before
public void setUp() {
a = PowerMockito.spy(new A());
}
/**
* Test of test method, of class A.
*/
#Test
public void testTest() throws Exception {
a.test();
PowerMockito.verifyPrivate(a, Mockito.times(10)).invoke("_test");
}
}
But using powermockito has drawbacks:
you cannot monitor coverage with tool as Jacoco and on the fly instrumentation
probably you are developing an hard to test design: you should use it only if you are working to a legacy and impossible to change code
Related
I am migration to AWS java sdk to version 2 to improve cold starts for infrequently used lambdas.
In version 1.x i used #DynamoDBTypeConvertedEnum to annotate enums and #DynamoDBDocument to store nested objects. how could i achieve the same, i don't want to change data stored in tables.
https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/client-configuration-starttime.html
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb-enhanced</artifactId>
</dependency>
The enum can be converted with the following annotation.
#DynamoDbConvertedBy(EnumAttributeConverter.class)
private JobType jobType;
Currently, you can write custom converters for any data type using the official dynamodb-enhanced client which contains DynamoDbConvertedBy annotation. There you can specify a converter class that implements the AttributeConverter interface for your data type.
Below is just my example of converter implementation for Map<EnumClass, String> type (the same way you can write it for any POJO):
#DynamoDbConvertedBy(EnumMapAttributeConverter.class) for the entity field's getter.
Class itself:
public class EnumMapAttributeConverter
implements AttributeConverter<Map<EnumClass, String>> {
#Override
public AttributeValue transformFrom(final Map<EnumClass, String> input) {
Map<String, AttributeValue> attributeValueMap =
input.entrySet().stream()
.collect(
Collectors.toMap(
k -> k.getKey().getValue(),
v -> AttributeValue.builder().s(v.getValue()).build()));
return AttributeValue.builder().m(attributeValueMap).build();
}
#Override
public Map<EnumClass, String> transformTo(final AttributeValue input) {
return input.m().entrySet().stream()
.collect(
Collectors.toMap(
k -> getEnumClassKeyByString(k.getKey()), v -> v.getValue().s()));
}
private EnumClass getEnumClassKeyByString(final String key) {
EnumClass enumClass = EnumClass.getByValue(key);
return enumClass != null ? enumClass : EnumClass.NOT_FOUND;
}
#Override
public EnhancedType<Map<EnumClass, String>> type() {
return EnhancedType.mapOf(EnumClass.class, String.class);
}
#Override
public AttributeValueType attributeValueType() {
return AttributeValueType.M;
}
}
I have a project by name Utility and it has a class by name Util as below:
public class Util {
public static String verify() {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpGet getRequest = new HttpGet("Endpoint");
HttpResponse response = httpClient.execute(getRequest);
// Parsing the response as String
String resp = .......
return resp;
}
}
I have another project by name Consumer and it has a class by name Service as below:
public class Service {
public String verify() {
String resp = Util.verify();
return resp;
}
}
I have added Utility as a dependency for Consumer as:
<dependency>
<groupId>com.my.company</groupId>
<artifactId>utility</artifactId>
<version>0.0.1</version>
<scope>provided</scope>
</dependency>
I have a unit test case for the Service class where I am mocking the Util class with PowerMockito as:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Util.class })
public class ServiceTest {
Service service = new Service();
#Before
public void setUp() throws Exception {
PowerMockito.mockStatic(Util.class);
PowerMockito.when(Util.verify()).thenReturn("mockedResponse");
}
#Test
public void testVerify() {
String resp = service.verify();
assertEquals(resp, "mockedResponse");
}
}
This test throws NotFoundException for ProtocolSocketFactory. Does anyone know why I see this exception? I am trying to mock the Util class, but PowerMockito tries to initialize the class before mocking it. If I add HttpClient as a dependency in pom.xml for project Consumer, then the error goes away and the mocking is successful.
The Powermockito version I am using is 1.6.2
java.lang.IllegalStateException: Failed to transform class with name com.my.company.Util. Reason: cannot find org.apache.commons.httpclient.protocol.ProtocolSocketFactory
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:266)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:180)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:68)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:114)
Caused by: javassist.CannotCompileException: cannot find org.apache.commons.httpclient.protocol.ProtocolSocketFactory
at javassist.expr.NewExpr.replace(NewExpr.java:215)
at org.powermock.core.transformers.impl.MainMockTransformer$PowerMockExpressionEditor.edit(MainMockTransformer.java:418)
at javassist.expr.ExprEditor.loopBody(ExprEditor.java:212)
at javassist.expr.ExprEditor.doit(ExprEditor.java:91)
at javassist.CtClassType.instrument(CtClassType.java:1431)
at org.powermock.core.transformers.impl.MainMockTransformer.transform(MainMockTransformer.java:74)
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:251)
... 55 more
Caused by: javassist.NotFoundException: org.apache.commons.httpclient.protocol.ProtocolSocketFactory
at javassist.ClassPool.get(ClassPool.java:450)
at javassist.bytecode.Descriptor.toCtClass(Descriptor.java:592)
at javassist.bytecode.Descriptor.getParameterTypes(Descriptor.java:439)
at javassist.expr.NewExpr.replace(NewExpr.java:188)
... 61 more
I have to test with JUnit a simple Singleton EJB that return a MongoClient.
I think I can try with Arquillian.
With this code I obtain an Java.lang.AssertionError because EJB isn't injected by the container. Where I'm wrong?
EJB class:
#Stateless
#Singleton
#ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class MongoClientProviderBean {
private Logger logger = Logger.getLogger(MongoClientProviderBean.class);
private MongoClient mongoClient = null;
#Lock(LockType.READ)
public MongoClient getMongoClient() {
return mongoClient;
}
#PostConstruct
public void init() {
try {
String address = "mongo-host";
int port = 27017;
//TODO: inject del indirizzo e porta
mongoClient = new MongoClient(address, port);
logger.info("Inizializzato mongoclient ("+address+", "+port+")");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
#PreDestroy
public void tearDown() {
mongoClient.close();
logger.info("Mongoclient chiuso");
}
}
Test Class:
#RunWith(Arquillian.class)
public class MongoClientProviderBeanTest {
private static final Logger logger = Logger.getLogger(MongoClientProviderBean.class);
#EJB
MongoClientProviderBean mongoClientProviderBean;
#Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap.create(JavaArchive.class, "test.jar")
.addClasses(MongoClientProviderBean.class, MongoClient.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
#Test
public void getMongoClient() throws Exception {
assertNotNull(mongoClientProviderBean);
/*
dummy test
*/
mongoClientProviderBean.getMongoClient();
}
}
Part of POM:
[...]
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>1.1.13.Final</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-weld-ee-embedded-1.1</artifactId>
<version>1.0.0.CR9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<version>2.3.5.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<scope>test</scope>
</dependency>
[...]
</dependencies>
[...]
I also tried with Wildfly managed container, but I obtain this exception:
org.jboss.arquillian.container.spi.client.container.LifecycleException: Could not start container
at org.jboss.as.arquillian.container.managed.ManagedDeployableContainer.startInternal(ManagedDeployableContainer.java:168)
at org.jboss.as.arquillian.container.CommonDeployableContainer.start(CommonDeployableContainer.java:123)
at org.jboss.arquillian.container.impl.ContainerImpl.start(ContainerImpl.java:199)
[...]Caused by: java.lang.IllegalArgumentException: WFLYLNCHR0001: The path 'null' does not exist
at org.wildfly.core.launcher.Environment.validateWildFlyDir(Environment.java:313)
at org.wildfly.core.launcher.AbstractCommandBuilder.validateWildFlyDir(AbstractCommandBuilder.java:652)
And JUnit can't start the container.
Weld alone won't inject EJB. Perhaps you can try with ejb-cdi-unit that extends weld, so that ejbs are injected like normal beans.
I am trying to mock static method with PowerMockito. I have referred to various stackoverflow answers such as this:Mocking static methods with PowerMock and Mockito
But I am getting : org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here exception.
I have spent hours debugging my code and google searching but to no avail. What am I missing here?
* Note: I am running it as a testng test. *
I have added comments in my code that may help you understand what I am trying to do.
The full stack trace is:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
at MyClassTest.testMethod1(MyClassTest.java:24)`
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo")) `
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.`
at MyClassTest.testMethod1(MyClassTest.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:348)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:343)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:305)
at org.testng.SuiteRunner.run(SuiteRunner.java:254)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
`
Below is my code:
Test Class
import static org.mockito.Matchers.anyString;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.testng.annotations.Test;
#Test
#RunWith(PowerMockRunner.class)
#PrepareForTest(AnotherClass.class)
public class MyClassTest {
MyClass myClass;
#Test
public void testMethod1() {
/*
* Mock static methods
*/
PowerMockito.mockStatic(AnotherClass.class);
BDDMockito.given(AnotherClass.yetAnotherMethod(anyString())).willReturn(Mockito.mock(String.class));
// call the method of system under test
myClass.method1();
// verify
PowerMockito.verifyStatic();
}
}
System Under Test:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public class MyClass {
public String method1() {
String result = AnotherClass.yetAnotherMethod("Pramithas");
return result;
}
}
AnotherClass.java:
import org.springframework.stereotype.Service;
public class AnotherClass {
public static String yetAnotherMethod(String s) {
return s;
}
}
You haven't created new object for MyClass
Do not try to mock primitive types or final classes
Removed #Test annotation
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.Matchers.anyString;
import org.mockito.BDDMockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(AnotherClass.class)
public class MyClassTest {`
MyClass myClass = new MyClass();
#Test
public void testMethod1() {
/*
* Mock static methods
*/
PowerMockito.mockStatic(AnotherClass.class);
BDDMockito.given(AnotherClass.yetAnotherMethod(anyString())).willReturn("any String");
// call the method of system under test
myClass.method1();
// verify
PowerMockito.verifyStatic();
}
}
This is verified. It should work.
I got your example working with some changes:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ AnotherClass.class })
public class MyClassTest {
#Before
public void setUp() {
myClass = new MyClass();
}
#Test
public void testMethod1() {
/*
* Mock static methods
*/
PowerMockito.mockStatic(AnotherClass.class);
BDDMockito.given(AnotherClass.yetAnotherMethod(Mockito.anyString())).willReturn("Hello");
// call the method of system under test
String a = myClass.method1();
// verify
PowerMockito.verifyStatic();
}
I added AnotherClass to PrepareForTest too and I force AnotherClass mock to return a String value because Mockito can't mock final classes and I can check that myClass behave as expected. Here is my Mockito and Powermock dependencies:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.7.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.0RC2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>1.7.0RC2</version>
<scope>test</scope>
</dependency>
I am beginner with JAX-RS webservice and its testcase.
My TestController class is as follows:
public class LotTypeMangementServiceTest {
private final String LOT_NAME = "lotName";
#Inject
private LotTypeManagementService lotTypeService;
#Test
private LotType testCreate() {
LotType newLotType = new LotType();
newLotType.setName(LOT_NAME);
//save
lotTypeService.createOrUpdate(newLotType);
Assert.assertNotNull(newLotType.getId());
return newLotType;
}
}
My LotTypeManagementService as follows:
#Stateless
public class LotTypeManagementService {
#PersistenceContext(unitName="primary")
private EntityManager em;
public void createOrUpdate(LotType lotType) {
if (lotType.getId() == null) { // Save New Label Type
em.persist(lotType);
} else { // Update Label Type
em.merge(lotType);
}
}
}
Now as you can see, LotTypeManagementService has EntityManager dependency.
In testclass, I've injected LotTypeManagementService. However, its dependency is not getting injected and hence I em object is NULL.
My persistence.xml file is as below:
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="primary">
<jta-data-source>java:jboss/datasources/lottype</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
My RestController is as below:
#RequestScoped
public class LotTypeResourceRESTService {
#Inject
private LotTypeManagementService lotTypeService;
}
I am using wildfly-9.0.1 server, java8, JAX-RS webservice, hibernate, jpa-2.1 and jUnit.
I found some solution on Stack Overflow like
Use #Inject or #Ejb
some change on persistance.xml <provider>org.hibernate.ejb.HibernatePersistence</provider>
em = (EntityManager) new nitialContext().lookup("java:/primary");
Like create dynamically container.
How can I do this correctly?