I am trying to write Unit test cases using power mockito.
When using annotations #RunWith(PowerMockRunner.class) I am getting the following compilation error:-
TypeMismatch: cannot convert from Class<PowerMockRunner> to Class<? extends Runner>
Here is the code snippet. Using junit 4.8.1 and power mock 1.6.2.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
public class XXXTest {
#Test
public void testOne() {
if (true)
System.out.println("Success");
}
}
I downloaded and added Powermock-Module-Junit4 jar and did not add the dependent jar Powermock-Module-Junit4-Common.jar. When added common jar Powermock-Module-Junit4-Common resolved the error.
Thanks,
Vasu.
Related
I am trying to unit test my service class but the mock returns null
package com.tgt.store.pricetask.pricetask_service;
import com.tgt.store.pricetask.model.PriceTaskMaster;
import com.tgt.store.pricetask.model.TaskModel;
import com.tgt.store.pricetask.repository.PriceTaskMasterRepository;
import com.tgt.store.pricetask.service.DataMigrationService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.time.LocalDateTime;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
#RunWith(SpringJUnit4ClassRunner.class)
public class DataMigrationServiceTest {
#Mock
PriceTaskMasterRepository priceTaskMasterRepository;
#InjectMocks
DataMigrationService dataMigrationService;
#Test
public void
testPriceTaskMasterService_whenTaskModelPassed_thenSavePriceTaskMaster() {
TaskModel taskModel = new TaskModel.TaskModelBuilder().setTaskID(1)
.setDueDate("2017-11-01T11:41:00+0000").setIsAlertable("A").setIsPriority("P").setLocationid("1234")
.createTaskModel();
PriceTaskMaster priceTaskMaster = new PriceTaskMaster.PriceTaskMasterBuilder().setId(1L).setTaskStatus("A")
.setAlertable("A").setPriority("P").setLocationId(1234)
.setDueDate(LocalDateTime.now()).createPriceTaskMaster();
when(priceTaskMasterRepository.insertPriceTaskMaster(any(PriceTaskMaster.class))).thenReturn(priceTaskMaster);
PriceTaskMaster savedPriceTaskMaster = dataMigrationService.savePriceTaskMaster(taskModel);
assertNotNull(savedPriceTaskMaster);
assertEquals("A", savedPriceTaskMaster.getTaskStatus());
assertEquals("P", savedPriceTaskMaster.getPriority());
assertEquals(1234, savedPriceTaskMaster.getLocationId().intValue());
assertEquals(123456789, savedPriceTaskMaster.getTcin().longValue());
verify((priceTaskMasterRepository), times(1)).insertPriceTaskMaster(priceTaskMaster);
}
}
In the above code, when call reaches the service class priceTaskMasterRepository is null. I am unable to figure out if I am missing something. I have tried RunWith SpringRunner and MockitoJUnitRunner but same result. Any help is appreciated.
Thank you in advance.
You will need to initialize the DataMigrationService field when using the #InjectMocks annotation. That will create an instance of the class under test as well as inject the mock objects into it.
#InjectMocks
DataMigrationService dataMigrationService = new DataMigrationService();
http://www.baeldung.com/mockito-annotations
If you're using JUnit to run your tests, then you should have something like this:
#Before
public void setup()
{
MockitoAnnotations.initMocks(this);
}
This ensures all your mocks are initialised. This is supposed to be unnecessary when using MockitoJUnitRunner.
I am trying to mock a final class
PowerMockito.mockStatic(TestFinalClass.class);
It is working from my eclipse when I run a single junit and add javaagent to my VM arguments
-javaagent:{path}/powermock-module-javaagent-1.6.4.jar
But when I try to run all test cases from command line using maven build command I am still getting "Cannot subclass final class"
Below is my snippet from pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4</version>
<configuration>
<argLine>-javaagent:{path}/powermock-module-javaagent-1.6.4.jar</argLine>
</configuration>
</plugin>
package test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(FinalClass.class)
public class Tests {
#Test
public void test() {
PowerMockito.mockStatic(FinalClass.class);
}
}
This works for me. If you add 'PowerMockRunner' and 'PrepareForTest' annotations you don`t need to use extra vm arguments.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(FinalClass.class)
public class TestFinalClass{
#Test
public void whenMockFinalClassMockWorks() {
FinalClass finalklass = PowerMockito.mock(FinalClass.class);
}
}
I got the code coverage using JaCoCo and need to make some changes related to it in the test class code. Those are as below:
I removed #RunWith annotation
Added #Rule and PowerMockRule class
Mentioned the Final and Static class in #PrepareForTest
#PrepareForTest(FinalClass.class, StaticClass.class)
public class Tests {
#Rule
public PowerMockRule rule = new PowerMockRule();
#Test
public void test() {
PowerMockito.mockStatic(FinalClass.class);
PowerMockito.mockStatic(StaticClass.class);
}
}
Also added the argline in surefire to overcome the final class problem while mocking.
<configuration>
<argLine>-javaagent:{path}/powermock-module-javaagent-1.6.4.jar</argLine>
</configuration>
We have an import problem with Eclipse :
the test class uses Assertions.assertThat
When hitting Ctrl + Shift + O to organize the imports, Eclipse replace Assertions.assertThat with StrictAssertions.assertThat
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
public class TheTest {
#Test
public void testName() {
assertThat(2).isEqualTo(2);
}
}
is replaced with :
import static org.assertj.core.api.StrictAssertions.assertThat; // change here !
import org.junit.Test;
public class TheTest {
#Test
public void testName() {
assertThat(2).isEqualTo(2);
}
}
And when we have some specific asserts that are only in Assertions (for lists), Eclipse add StrictAssertions to the imports.
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import org.junit.Test;
public class TheTest {
#Test
public void testName() {
assertThat(2).isEqualTo(2);
assertThat(new ArrayList<>()).isEmpty();
}
}
is changed to :
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.StrictAssertions.assertThat; // this import was added
import java.util.ArrayList;
import org.junit.Test;
public class TheTest {
#Test
public void testName() {
assertThat(2).isEqualTo(2);
assertThat(new ArrayList<>()).isEmpty();
}
}
It seems that Assertions extends StrictAssertions, so their is no problem using StrictAssertions, but why is Eclipse not using the extended class ?
Looks like, because assertThat(int actual) is defined in StrictAssertions and not hidden by Assertions, Eclipse decides to import from StrictAssertions.
Also, for organizing imports Eclipse seems to ignore Type Filters - so even that won't help.
It seems that Assertions extends StrictAssertions, so their is no problem using StrictAssertions
Not for your current setup, but StrictAssertions has been removed with AssertJ 3.2.0. So when upgrading to a newer version of AssertJ StrictAssertions will get in your way.
I'd suggest you upgrade to 3.2.0 or later, if it is possible with your project.
Is it a bug of Powermock or I'm doing sth wrong?
The following test should pass, but failed with:
trackBugPartialMockCountMore(com.xiaomi.finddevice.test.testcase.PowerMockBug)
org.mockito.exceptions.verification.TooManyActualInvocations:
classToMock.foo();
Wanted 1 time:
-> at com.xiaomi.finddevice.test.testcase.PowerMockBug.trackBugPartialMockCountMore(PowerMockBug.java:24)
But was 3 times. Undesired invocation:
-> at com.xiaomi.finddevice.test.testcase.PowerMockBug.trackBugPartialMockCountMore(PowerMockBug.java:22)
When I remove #PrepareForTest(ClassToMock.class), every thing goes well and the test get passed.
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassToMock.class)
public class PowerMockBug {
#Test
public void trackBugPartialMockCountMore() {
ClassToMock mock = mock(ClassToMock.class);
when(mock.foo()).thenCallRealMethod();
mock.foo();
verify(mock).foo();
}
}
class ClassToMock {
public int foo() { return 0x10; }
}
VERSION: powermock-mockito-junit-1.6.3
In your example you don't need to use PowerMock because you are not mocking/spying a final or static method. You can safely remove both #RunWith and #PrepareForTest annotations. Only mockito is needed for your purposes
I have some simple classes I'm using to see if I can get powermock to work:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(Foo.class)
public class FooTest
{
#Test
public void testFoobar(){
Foo test = PowerMock.createPartialMock(Foo.class, "foobar");
PowerMock.replay(test);
}
}
and
public class Foo
{
public String foobar(String aString){
return aString + " blah";
}
}
When I try to run this unit test, it tells me:
java.lang.NoClassDefFoundError: org/easymock/classextension/internal/ClassProxyFactory$MockMethodInterceptor
...
I have no idea why its doing this. Please help.
Make sure you're including EasyMock in your class path when using PowerMock... you can find the download page here.
According to the Wiki on PowerMock, it states that EasyMock is a dependency.