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.
Related
#RunWith(SpringRunner.class)
public class TestService {
#Test
#EnabledIf("Instant.now().atZone(ZoneId.of(\"Asia/Kolkata\")).getDayOfWeek() == DayOfWeek.MONDAY")
public void test() {
System.out.println("The day is Monday");
}
}
running using mvn -Dtest=TestService test
#EnabledIf is not working, it is executing the test even the day is not Monday
Your code has two big problems:
First, the test class is annotated with #RunWith(SpringRunner.class) and (because the test runs) the test method is annotated with #org.junit.Test
This means that the test is running using the JUnit4 testing framework and JUnit4 knows nothing about the #EnabledIf annotation and ignores it.
If you want to use the #EnabledIf annotation you must make your test into a JUnit5 test and for that you must change your test class to
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
public class TestService {
#Test
#EnabledIf("Instant.now().atZone(ZoneId.of(\"Asia/Kolkata\")).getDayOfWeek() == DayOfWeek.MONDAY")
public void test() {
System.out.println("The day is Monday");
}
}
Because of the second problem that doesn't completely solve your problem. The documentation for #EnabledIf states:
A container or test may be enabled or disabled based on the boolean return of a method via the #EnabledIf and #DisabledIf annotations. The method is provided to the annotation via its name.
That means that you cannot provide some arbitrary expression as the argument of the #EnabledIf annotation - you need to implement the expression in a method.
When adding that method your test class might look like this:
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.ZoneId;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
public class TestService {
#Test
#EnabledIf("onMonday")
public void test() {
System.out.println("The day is Monday");
}
static boolean onMonday() {
return Instant.now().atZone(ZoneId.of("Asia/Kolkata")).getDayOfWeek() == DayOfWeek.MONDAY;
}
}
If however you intended to use org.springframework.test.context.junit.jupiter.EnabledIf (instead of org.junit.jupiter.api.condition.EnabledIf - unfortunately your question is not clear about that) then you need to adjust the imports and provide a SpEL-Expression for the condition:
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.ZoneId;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.EnabledIf;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
public class TestService {
#Test
#EnabledIf("#{T(java.time.Instant).now().atZone(T(java.time.ZoneId).of(\"Asia/Kolkata\")).getDayOfWeek() == T(java.time.DayOfWeek).MONDAY}")
public void test() {
System.out.println("The day is Monday");
}
}
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 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.
I am trying to have RunWith(PowerMockRunner.class) working with my existing package annotation.
Versions:
powermock 1.4.12 mockito 1.9.0 junit 4.8.2
package-info.java // this is for the package annotation
#TestAnnotation(version="1.0")
package com.smin.dummy;
TestAnnotation.java // this is the the metadata annotation class for package "com.smin.dummy"
package com.smin.dummy;
import java.lang.annotation.*;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PACKAGE)
public #interface TestAnnotation {
String version();
}
A.java
package com.smin.dummy;
public class A {
private static Package myPackage;
private static TestAnnotation version;
static {
myPackage = TestAnnotation.class.getPackage();
version = myPackage.getAnnotation(TestAnnotation.class);
}
public static String getVersion() {
return version.version();
}
}
MockA.java
package com.smin.dummy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.smin.dummy.A;
#RunWith(PowerMockRunner.class) //comment out this line to see the difference
#PrepareForTest(A.class)
public class MockA {
#Test
public void test_mocked() throws Throwable {
String thisVersion = A.getVersion();
System.out.println(thisVersion);
}
}
In the unitest MockA.java, if I don't use RunWith(PowerMockRunner.class), I will get the thisVersion printed 0.1 as expected. But after adding RunWith(PowerMockRunner.class), thisVersion turns into null. I suspect PowerMockRunner is doing some funny thing with the package annotation here, anybody has any idea? see the mini version of my code below:
Building on #Alban's sleuthing in the comments, it looks like adding this annotation to your test case should circumvent the problem:
#PowerMockIgnore("com.smin.dummy.TestAnnotation")