Mockito mock constructor example - java

I'm trying to instantiate a mock object with Mockito. I found two examples in the article here, still this article is a very bad example for a newbie like me in Mockito.
Can somebody give me a better example of how it is done with either of the two options?

Simple when doing PowerMockito
public class A {
private final String name;
public A(String name) {
this.name= name;
}
public String sayHello() {
return "Hi " + this.name;
}}
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class)
public class MockA {
#Test
public void testSayHello throws Throwable {
A a = mock(A.class);
when(a.sayHello()).thenReturn("Hi PowerMockito");
PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a);
assertThat(new A("I am mockcked").sayHello(), equalTo("Yes, you are!"));
}
}
Dependencies
<dependencies>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>{mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

Related

PowerMock private void method with arguments

I'm looking for a unit test for Controllers using Mockito and PowerMock. Every controller has only private void methods with a single argument and a #Autowired service dependency:
public class ProjectController {
private ProjectServiceImpl service;
#Autowired
public void setInjectedBean(ProjectServiceImpl service) {
this.service = service;
}
private void createProject(String someString) {
// do stuff by calling service.doSomething(someString)
}
}
ProjectServiceImpl is annotated with #Service and has only a public void method with a String as argument. As it is too simple, I didn't bother providing the code.
My last attempt to accomplish that test looks like this:
#RunWith(PowerMockRunner.class)
#ExtendWith(MockitoExtension.class)
#PrepareForTest({ProjectController.class, ProjectServiceImpl.class})
class ProjectControllerTest {
#InjectMocks
private ProjectController controller;
#Mock
private ProjectServiceImplservice;
#Test
void createProject() throws Exception {
controller = PowerMockito.spy(new ProjectController());
PowerMockito.doNothing().when(controller, "createProject", new String(""));
}
}
Question 1: is it possible to make PowerMock work aside of Mockito?
Question 2: using PowerMock, what's the most appropriate way of calling for a private void method with argument?
IMPORTANT: Before marking this post as a duplicate, I personally challenge you finding any content how to do so. It seems like there is just no content showing not only how to make both work together, but make PowerMockito calls for a private void method with one or more arguments.
dependencies used for PowerMock:
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>

PowerMock is not intercepting new Instances

Hi I´m trying to test some legacy code that uses command patron. I couldn´t make work PowerMock propperly and I tryed to make a simple example to test if it could work.
I think that the problem is that the method whenNew() or expectNew() is not intercepting when in the original code a "new" instance is declared.
Here is the code:
ClassToTest
public class ClassToTest {
public ClassToTest() {
}
public ClassInstance getClassInstance() {
ClassInstance a = new ClassInstance(1);
return a;
}
}
ClassInstance
public class ClassInstance {
private int detector;
public ClassInstance(int detector) {
this.detector = detector;
}
public int getDetector() {
return detector;
}
public void setDetector(int detector) {
this.detector = detector;
}
}
The test
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClassToTestTest.class, ClassInstance.class})
public class ClassToTestTest {
#Test
public void test() throws Exception {
ClassInstance n = new ClassInstance(2);
PowerMockito.whenNew(ClassInstance.class).withAnyArguments().thenReturn(n);
ClassToTest c = Mockito.spy(ClassToTest.class);
System.out.println(c.getClassInstance().getDetector());
}
}
And here is the pom.xml.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.18.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
So when I run the test, the expected value if PowerMockito intercepts the new instance should be 2 but the console gives me 1...

Not able to use #Rule & #RunWith annotation, but the deprecated initmocks() works

I am working on a basic test-driven development learning of a simple java program which provides portfolio value for the stocks.
I am having 2 classes,Portfolio.java & Stock.java which depicts the portfolio & stock models. An interface StockService.java is used in abstract manner to get real-time stock price.
PortfolioTest.java is the class in which I am trying to write unit-tests for the features of portfolio by mocking this StockService using Mockito.
I am able to use the deprecated MockitoAnnotations.initMocks(this); & run my tests but getting null pointer exception if try to use #Rule or #RunWith annotations.
Stock.java
public class Stock {
private String name;
private int quantity;
public Stock(String name, int quantity) {
this.name = name;
this.quantity = quantity;
}
public String getName() { return name; }
public float getQuantity() { return quantity; }
}
Portfolio.java
import java.util.List;
public class Portfolio {
private List<Stock> stocks;
private StockService stockService;
private Float portfolioValue;
public Portfolio(List<Stock> stocks, Float portfolioValue) {
this.stocks = stocks;
this.portfolioValue = portfolioValue;
}
public void setStockService(StockService stockService) { this.stockService = stockService; }
public Float calculateMarketValue() {
Float marketValue = 0.0f;
for(Stock stock: this.stocks) {
marketValue += (stock.getQuantity()*stockService.getRealtimePrice(stock.getName()));
}
return marketValue;
}
public Boolean isInProfit() {
return (portfolioValue<calculateMarketValue()?true:false);
}
}
StockService.java
public interface StockService {
public float getRealtimePrice(String name);
}
pom.xml
<project>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.5.13</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<finalName>mockito-basic</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>
PortfolioTest.java
//#RunWith(MockitoJUnitRunner.class)
public class PortfolioTestMockAnnotations {
//#Rule public MockitoRule rule = MockitoJUnit.rule();
#Mock
StockService stockService;
#InjectMocks
Portfolio portfolio;
#BeforeAll
static void setUp() {
}
#BeforeEach
void init(){
MockitoAnnotations.initMocks(this);
System.out.println(stockService);
when(stockService.getRealtimePrice("infosys")).thenReturn(2200.0f);
when(stockService.getRealtimePrice("reliance")).thenReturn(3100.0f);
when(stockService.getRealtimePrice("indiamart")).thenReturn(4000.0f);
List<Stock> stocks = new ArrayList<>();
stocks.add(new Stock("infosys",10));
stocks.add(new Stock("reliance", 5));
portfolio = new Portfolio(stocks, 35000.0f);
portfolio.setStockService(stockService);
}
#Test
public void calculateMarketValueTest() {
Assertions.assertEquals(portfolio.calculateMarketValue(),37500);
}
#Test
public void calculateIsInProfitTest() {
Assertions.assertTrue(portfolio.isInProfit());
}
}
Using initmocks() in the PortfolioTest.java runs the test smoothly.
Using #Rule, throws NPE
Using #RunWith, throws NPE
Please suggest the correct way for using #Rule & #RunWith in a smooth. Also provide brief difference between these 3 mechanisms of instantiating mocks.
Your POM reveals that you might somehow mix JUnit5 and JUnit4. There are two annotations to declare method as test:
#org.junit.Test // for JUnit4
#org.junit.jupiter.api.Test // for JUnit5
If you annotate for JUnit4 and run test as JUnit4 test everything should be fine.
But if you annotate with JUnit5 and run as JUnit5 test things will be a bit different. JUnit5 does not use #Rule nor #RunWith but has its own way to initialize mocks. Article which might explain why something works and something not.
In a nutshell, for running as JUnit5 your class should have annotation:
#ExtendWith(MockitoExtension.class)
because #Rule or RunWith does not work anymore. This annotation needs dependency:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.0</version>
<scope>test</scope>
</dependency>
I run only JUnit5 and have these dependencies
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.5.2</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.0</version>
<scope>test</scope>
</dependency>
Related question
In Junit5, #RunsWith() is replaced with #ExtendWith({MockitoExtension.class}), where MockitoExntension is coming from
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.11.2</version>
<scope>test</scope>
</dependency>
3.11.2 is the current version at the time I am posting the solution. For more info you can visit: Mockito and Junit5

Test annotation processor with spring test

I am using junit to test my annotation processor. The test is failing. It seems like never entering the joinpoint, without any exception.
My annotation is like this:
#Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
#Retention(RetentionPolicy.RUNTIME)
public #interface EventListener {
boolean isListening() default true;
boolean isDefaultListener() default true;
Class<SomeListener> subscriber() default None.class;
public static class None implements SomeListener {
... ...
}
}
And the processor like this:
#Aspect
public class ListenerProcessor {
#Pointcut("#annotation(com.xxx.common.event.annotation.EventListener)")
public void sign() {}
#Before("sign()")
public void anAdvice(JoinPoint joinPoint) { ***//this has never executed***
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Method method = signature.getMethod();
EventListener anno = method.getAnnotation(EventListener.class);
if (anno != null) {
if (anno.isListening()) {
if (anno.isDefaultListener())
doDefault();
else {
Class<SomeListener> clazz = anno.subscriber();
doCustomize(clazz);
}
} else {
... ...
}
}
}
... ...
}
My test is like this:
#RunWith(SpringRunner.class)
#ContextConfiguration(locations = "classpath:applicationContext.xml")
public class EventListenerTest {
#Test
public final void test() {
//given
Long bef = countEvents();
//when
TestEntity1 t1 = appWithDefaultListener();
//then
TestEntity1 t2 = getEntityLike(t1);
Long aft = countEvents();
assertThat(t1).isEqualToComparingFieldByField(t2);
assertThat(aft).isEqualTo(bef+1);
}
#Transactional
#EventListener(isListening=true, isDefaultListener=true) ***//this seems does'nt work***
private TestEntity1 appWithDefaultListener() {
TestEntity1 t1 = new TestEntity1(...);
return myRepository.save(t1);
}
#Transactional(readOnly = true)
private TestEntity1 getEntityLike(TestEntity1 t1) {
TestEntity1 t2 = myRepository.findOne(Example.of(t1));
return t2;
}
}
My applicationContext.xml is like this:
<aop:aspectj-autoproxy proxy-target-class="true">
<aop:include name="eventProcessor"/>
</aop:aspectj-autoproxy>
<context:annotation-config />
<bean id="eventProcessor"
class="com.xxx.common.event.process.EventListenerProcessor"
scope="prototype"/>
And My pom has these dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.13.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>2.6.0</version>
</dependency>
What am I missing? Or any thing goes wrong?
Don't define appWithDefaultListener() and getEntityLike() as private methods in your test class.
Instead, you need to define them as non-private methods in another class that you configure as a bean in the test's ApplicationContext. Then have that bean #Autowired into your test class and invoke the methods via that reference so that your aspect is applied.

powermock+easymock+testng for testing a final class

Using these dependencies in my pom.xml
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-test-easymock-testng</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.5.5</version>
</dependency>
This is my code, where Dispute is a class of type final.
#PrepareForTest(Dispute.class)
public void testProcessChargebackUpdates() {
final List<BraintreeGateway> credentials = new LinkedList<BraintreeGateway>();
credentials.add(credential);
// Dispute dispute = control.createMock(Dispute.class);
Dispute dispute = PowerMock.createMock(Dispute.class);
}
Gives cannot instantiate final class.
First of you need these dependencies :
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-test-easymock-testng</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-testng</artifactId>
<version>1.4.9</version>
</dependency><dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.5.5</version>
</dependency>
Then you need this in your class, #Prepare annotation with the final class to be mocked, as
well as the getObjectFactory method to be defined in the class.
#PrepareForTest(Dispute.class)
public void testProcessChargebackUpdates() {
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new PowerMockObjectFactory();
}
}

Categories