Mock static class java

PowerMock(+Mockito) +TestNG и имитация вызова (mock) статических методов

На хабре уже была статья с примерами использования PowerMock, но в ней не хватает такого описания, как имитации вызова статических методов как самостоятельных «единиц» в классе, так и в гибридном использовании, когда часть статических методов у класса подменяются «заглушкой», а часть вызываются реально. Попробую исправить эту нишу.

Для начала создадим демонстрационный класс со статическими методами (commit):

public class ClassStatic < static String getValue() < return "value"; >static String getValue(final String s) < return getValue() + s; >> 
import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @Test(groups = ) public class ClassStaticTest < @DataProvider public Object[][] data() throws Exception < return new Object[][], >; > @Test public void testGetValueVoid() throws Exception < Assert.assertEquals(ClassStatic.getValue(), "value"); >@Test(dataProvider = "data", dependsOnMethods = ) public void testGetValueAttribute(final String v, final String r) throws Exception < Assert.assertEquals(ClassStatic.getValue(v), r); >> 

До этого момента мы ни разу не использовали PowerMock, так как он нам не требовался. Теперь же, чтобы сделать «заглушку» для статических методов, создадим «костяк» тестового класса:

import org.powermock.modules.testng.PowerMockObjectFactory; import org.testng.IObjectFactory; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test; @Test(groups = ) public class ClassStaticMockTest < @ObjectFactory public IObjectFactory setObjectFactory() < return new PowerMockObjectFactory(); >> 

Мы создали класс ClassStaticMockTest, в котором переопределили Object Factory для TestNG (документация)

Добавим тест с «заглушкой» для статического метода:

import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.testng.PowerMockObjectFactory; import org.testng.Assert; import org.testng.IObjectFactory; import org.testng.annotations.DataProvider; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test; import static org.mockito.MockitoAnnotations.Mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @Test(groups = ) @PrepareForTest() public class ClassStaticMockTest < @Mock public ClassStatic classStatic; @DataProvider public Object[][] data() throws Exception < return new Object[][], >; > @ObjectFactory public IObjectFactory setObjectFactory() < return new PowerMockObjectFactory(); >@Test(dependsOnGroups = ) public void mockGetValueVoid() throws Exception < mockStatic(ClassStatic.class); when(ClassStatic.getValue()).thenReturn("newValue"); Assert.assertEquals(ClassStatic.getValue(), "newValue"); >>

Остался заключительный «аккорд» — гибридный тест, в котором вызов одного статического метод перекрыт «заглушкой», а для другого делается реальный вызов (commit):

import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.testng.PowerMockObjectFactory; import org.testng.Assert; import org.testng.IObjectFactory; import org.testng.annotations.DataProvider; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test; import static org.mockito.MockitoAnnotations.Mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; /** Created by borz on 06.07.13. */ @Test(groups = ) @PrepareForTest() public class ClassStaticMockTest < @Mock public ClassStatic classStatic; @DataProvider public Object[][] data() throws Exception < return new Object[][], >; > @ObjectFactory public IObjectFactory setObjectFactory() < return new PowerMockObjectFactory(); >@Test(dependsOnGroups = ) public void mockGetValueVoid() throws Exception < mockStatic(ClassStatic.class); when(ClassStatic.getValue()).thenReturn("newValue"); Assert.assertEquals(ClassStatic.getValue(), "newValue"); >@Test(dataProvider = "data", dependsOnMethods = ) public void testGetValueAttribute(final String v, final String r) throws Exception < mockStatic(ClassStatic.class); when(ClassStatic.getValue()).thenReturn("newValue"); when(ClassStatic.getValue(v)).thenCallRealMethod(); Assert.assertEquals(ClassStatic.getValue(v), r); >> 

Мы перекрываем вызов метода getValue() и указываем, что при вызове getValue(String value) будет вызван реальный метод у класса, который уже внутри себя вызывает getValue() .

Читайте также:  Php require once mysql

Как «жизненный» пример потребности использования имитации вызова статических методов является «перекрытие» данных методов «заглушками» при тестировании других классов/методов (commit).

Добавляем класс, использующий у себя статический метод ClassStatic.getValue() :

public class ClassUseStatic < public String getValue() < return ClassStatic.getValue() + "noStatic"; >> 

И добавляем тест для метода ClassUseStatic.getValue() с переопределением вызова ClassStatic.getValue() :

import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.testng.PowerMockObjectFactory; import org.testng.Assert; import org.testng.IObjectFactory; import org.testng.annotations.DataProvider; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test; import static org.mockito.MockitoAnnotations.Mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @Test(groups = , dependsOnGroups = ) @PrepareForTest() public class ClassUseStaticTest < @Mock public ClassStatic classStatic; @DataProvider public Object[][] data() throws Exception < return new Object[][], >; > @ObjectFactory public IObjectFactory setObjectFactory() < return new PowerMockObjectFactory(); >@Test(dataProvider = "data") public void testGetValue(String value, String result) throws Exception < mockStatic(ClassStatic.class); when(ClassStatic.getValue()).thenReturn(value); ClassUseStatic testClass = new ClassUseStatic(); Assert.assertEquals(result, testClass.getValue()); >> 

PS: Все примеры можно найти на GitHub.

UPD: добавил пример имитации вызова статических методов при тестировании «обычных» классов.

Источник

Use Mockito to Mock Static Method in Java

Use Mockito to Mock Static Method in Java

This tutorial demonstrates how we can use the mockito to mock the static method in Java.

Mock Static Method in Java

Mocking Static Methods are required when performing unit testing in Java. Before the Mockito 3.4.0 version, we need to use PowerMock to mock the static and private methods.

With Mockito 3.4.0 , we can directly mock the static methods. This tutorial demonstrates how to mock static methods using mockito in Java.

Add Maven Dependency

Before starting with mockito , we need to add it to our system. To mock the static method, we require inline mock-making from mockito inline mocking.

The mockito-inline is developed separately for community feedback which provides the mocking facility for static methods, and the final class, which were unmockable previously; here is the maven dependency for mockito inline mocking:

   org.mockito   mockito-inline   4.6.1   test  

Add this dependency to pom.xml of your maven system, and you are good to go.

Different Code Examples Using Mockito Inline Mocking

Let’s first decide on a system we can apply to mock static methods. Let’s create a simple class with two methods, one with arguments and one without arguments. See Example:

package delftstack;  import java.util.stream.IntStream;  class Mock_Static_Method    public static String get_Value()   return "delftstack";  >   public static int addition(int. args)   return IntStream.of(args).sum();  > > 
  1. The first method returns the value delftstack and doesn’t take any argument.
  2. The second method takes arguments and returns their sum.

Mock Static Class

Before mocking the static method, we need to mock the static class. Here is the code example of how to mock a static class using mockito in Java:

try (MockedStatic Mock_Static_Class = mockStatic(AppStatic.class))   //Here, we can record mock expectations, test code, and verify mock  > 

The MockedStatic in the above code represents the scoped and active mocks of type static methods. The mockStatic is used to verify static method invocations.

Mock Static Method with No Arguments

Let’s try to mock the first method, get_Value() , which takes no arguments and returns the value delftstack . We will try to mock the get_Value() method and return the value delftstack1 ; see the example:

@Test public void Testing_Get_Value()   //Outside the scope  assertEquals("delftstack", Mock_Static_Method.get_Value());   try (MockedStatic Mock_Static = mockStatic(Mock_Static_Method.class))    Mock_Static.when(Mock_Static_Method::get_Value).thenReturn("delftstack1");   //Inside the scope  assertEquals("delftstack1", Mock_Static_Method.get_Value());  Mock_Static.verify(Mock_Static_Method::get_Value);  >   //Outside the scope  assertEquals("delftstack", Mock_Static_Method.get_Value()); > 

The code above mocks the static method get_Value(), and now, outside the scope, the method will return delftstack , and inside the scope, it will return delftstack1 .

Mock Static Method with Arguments

There is not much difference between mocking a static method with arguments and a static method without arguments.

To mock static method with arguments, we can use flexible argument-matches in expectations and lambda expression to invoke the methods; see example:

@Test public void Testing_Addition()   assertEquals(3, Mock_Static_Method.addition(1, 2));   try (MockedStatic Mock_Static = mockStatic(Mock_Static_Method.class))    Mock_Static.when(() -> Mock_Static_Method.addition(anyInt(),  anyInt())).thenReturn(10);   assertEquals(10, Mock_Static_Method.addition(1, 2));  Mock_Static.verify(() -> ClassWithStaticMethod.addition(1, 2));  >   assertEquals(3, Mock_Static_Method.addition(1, 2)); > 

The code above mocks the static method with arguments from the code above.

The code above will return the sum of given arguments as it is mocking the IntStream.of(args).sum() , which is used to calculate the sum of given arguments. Outside the scope, the method will return the sum 3 , and inside the scope, it should return the value 10 .

Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.

Источник

Mock Static Methods with Mockito

Learn to mock the static methods using Mockito in unit testing in Java. Previously, we had to use PowerMock to mock private and static methods, but starting version 3.4.0, Mockito supports mocking static methods directly. Read getting started with Mockito guide for setup instructions.

To mock static methods, we need to use the inline mock-making facility provided by mockito-inline module. Note that this module is separate from mockito-core module for some time, and in a future release it will be merged with mockito-core itself.

The mockito-inline module has been developed separately for community feedback and provides the mocking capability for static methods; and final classes and methods which previously were considered unmockable. It uses a combination of both Java instrumentation API and sub-classing rather than creating a new class to represent a mock.

 org.mockito mockito-inline 4.6.1 test 

For demo purposes, we are creating a simple class with two methods.

  • The first method does not take any argument and returns the string value “foo”.
  • The second method takes a variable number of int arguments and returns their sum.
class ClassWithStaticMethod < public static String getVal() < return "foo"; >public static int add(int. args) < return IntStream.of(args).sum(); >>

The MockedStatic represents an active and scoped mock of a type’s static methods. Due to the defined scope of the static mock, it returns to its original behavior once the scope is released. To define mock behavior and to verify static method invocations, use the MockedStatic reference returned from the Mockito.mockStatic() method.

It is necessary to call ScopedMock.close() method to release the static mock once it has been used and is no longer needed. It is therefore recommended to create this object within a try-with-resources statement unless when managed explicitly.

The following is the syntax to use the MockedStatic class in a unit test.

try (MockedStatic mock = mockStatic(AppStatic.class)) < //record mock expectations //test code //verify mock >

If we do not use try-with-resources block, as suggested, the mocking/stubbing/verifying will work as expected but leaves the class in a mocked state.

3. Mocking No-Args Static Methods

Let us mock the first method getVal() that takes no arguments and returns a String value «foo» . We are mocking the getVal() method and returning the value «bar» from the mock.

When we invoke the getVal() method, outside the mock scope, we should the value as “bar” and inside the scope, we should get the value “foo”.

@Test public void testGetVal() < //Outside scope assertEquals("foo", ClassWithStaticMethod.getVal()); try (MockedStatic mockStatic = mockStatic(ClassWithStaticMethod.class)) < mockStatic.when(ClassWithStaticMethod::getVal).thenReturn("bar"); //Inside scope assertEquals("bar", ClassWithStaticMethod.getVal()); mockStatic.verify(ClassWithStaticMethod::getVal); >//Outside scope assertEquals("foo", ClassWithStaticMethod.getVal()); >

4. Mocking a Static Method with Arguments

Mocking the static methods that accept arguments and return values is pretty much same as the previous section. Additionally, we can use flexible argument-matchers in expectations.

Note that we are using the lambda expression syntax for invoking the static method.

@Test public void testAdd() < assertEquals(3, ClassWithStaticMethod.add(1, 2)); try (MockedStatic mockStatic = mockStatic(ClassWithStaticMethod.class)) < mockStatic.when(() ->ClassWithStaticMethod.add(anyInt(), anyInt())).thenReturn(10); assertEquals(10, ClassWithStaticMethod.add(1, 2)); mockStatic.verify(() -> ClassWithStaticMethod.add(1, 2)); > assertEquals(3, ClassWithStaticMethod.add(1, 2)); >

In this tutorial, we learned to create, record expectations and verify the mocks have static methods. Make sure you understand the fact that a static mock is expected to be used in a defined scope, and the module mockito-inline can be merged with mockito-core in the future.

Источник

Оцените статью