Test static class java

Проверка статичности метода с использованием отражения в Java

Узнайте, как мы можем проверить, является ли метод статическим или нет.

1. Обзор

В этом кратком руководстве мы обсудим, как мы можем проверить, является ли метод статическим или нет в Java, используя API Reflection .

2. Пример

Чтобы продемонстрировать это, мы создадим Статическую утилиту класс с некоторыми статическими методами:

public class StaticUtility < public static String getAuthorName() < return "Umang Budhwar"; >public static LocalDate getLocalDate() < return LocalDate.now(); >public static LocalTime getLocalTime() < return LocalTime.now(); >>

3. Проверьте, является ли Метод статическим

Мы можем проверить, является ли метод статическим или нет, используя модификатор . isStatic метод :

@Test void whenCheckStaticMethod_ThenSuccess() throws Exception

В приведенном выше примере мы сначала получили экземпляр метода, который мы хотим протестировать с помощью метода Class.GetMethod . Как только у нас будет ссылка на метод, все, что нам нужно сделать, это просто вызвать метод Modifier.isStatic .

4. Получить все статические методы класса

Теперь, когда мы уже знаем, как проверить, является ли метод статическим или нет, мы можем легко перечислить все статические методы класса:

@Test void whenCheckAllStaticMethods_thenSuccess() < ListmethodList = Arrays.asList(StaticUtility.class.getMethods()) .stream() .filter(method -> Modifier.isStatic(method.getModifiers())) .collect(Collectors.toList()); Assertions.assertEquals(3, methodList.size()); > 

В приведенном выше коде мы только что проверили общее количество статических методов в нашем классе Статическая утилита .

5. Заключение

В этом уроке мы видели, как мы можем проверить, является ли метод статическим или нет. Мы также видели, как получить все статические методы класса.

Как всегда, полный код для этого примера доступен на GitHub .

Читайте ещё по теме:

Источник

Unit Testing static classes and methods in Java

Hello, I wanted to share a situation I found a couple of days ago, whilst working for my project for Twilio April Hackathon. I was working on the server-side project and creating endpoints for my product roadmap. What I insist on is testing my code, especially the logic. It’s a habit I am actively trying to make. Let’s take this service method that validates a phone number using Twilio API. Alt Text We invoke ‘fetch’ method on com.twilio.rest.lookups.v1.PhoneNumber to receive an instance of PhoneNumberFetcher.class which will later get all the information on the provided phone number if it exists. Great!
Now, how do we test this? We cannot. We cannot mock static classes. So, we need a way to ‘inject’ our Twilio API call into our logic and test our code as is without worrying about the response from the external API. Check the wrapper below: Alt Text Now, we can update our service method:
*Create getter and setter for TwilioSmsApiWrapper class
Alt Text Now we can happily create a unit test for our service method: Alt Text That’s it. Now you have decoupled you ThirdParty Logic from your service and you can unit test your logic without relying on real API calls.
Happy coding.

Читайте также:  Шифровать пароль в python

Top comments (0)

ReasonReact, Auth0 and 3rd Party React Components

Git and GitHub for Beginners — The Basics

React Design Patterns

Источник

3 Best Practices to Test a Code That Calls Static Methods

If you’ve ever developed unit tests in a serious project, you should know how frustrating it is to test a code that calls static methods. Here I’ll try to summarize 3 best practices that I normally use to test such a code.

When does a static method requires a special care in unit tests?

Not all static method calls make developing unit tests difficult. We’re all familiar with some well-known libraries like Apache Commons or Google Guava. Typically calling a utility class from such libraries in your code doesn’t need to be cared for. Why? Because a static call can be problemtic, only if it matches at least one of the following criteria:

  1. Having some external dependencies (e.g depends on another class, accesses database, makes an API call to other modules or external systems, etc.)
  2. Having some internal static state (e.g. if it caches something in a private static field)

Why static code is difficult to test?

Because the logic is assigned to the class definition itself not to instances. Considering the fact that you can’t overwrite a static method in Java, you can not overwrite a static behavior in a dummy implementation of the class for your unit tests.

Now consider the following UserService that has a disableUser method. It accepts a user identifier, disables it and persists the result and finally returns the updated user object:

The UserDao class wraps data access logic in its static methods, so it requires database access to do its business. If it was an instance method, we could extend it for our unit tests and overwrite the methods as needed. That’s actually a basis for our first solution to this problem.

Solution 1: Use dependency injection

If you have access to the source of the static method and you can/allowed to refactor it, the best solution is to change the static method to instance methods. Then you can simply inject the containing class into your code. In case of our UserDao class, if we apply such a change, then we can call it as below:

Читайте также:  Python запрос ip адреса

This allows you to use a mocking framework to mock the behavior of the UserDao in your unit tests. In the following example, I’m using Mockito to do that.

@RunWith(MockitoJUnitRunner.class) public class UserServiceTest < @Mock // Mocking the UserDao so it'll not make database calls UserDao userDaoMock; @InjectMocks // Asking Mockito to inject all mocked instances into this class UserService userService = new UserService(); @Test public void disableUserTest() < User sampleUser = new User(); sampleUser.setEnabled(true); // Tell the finder method of the DAO class what to do if it's called when(userDaoMock.findUserById(1)).thenReturn(sampleUser); sampleUser = userService.disableUser(1); assertFalse(sampleUser.isEnabled()); >>

I think it always worth to consider this solution as the first option. Regarding the DAO implementation specifically, you can use the repository pattern and implement it using a framework like Apache DeltaSpike. However it’s not always possible to refactor the static method. It can be due to its impact on other parts of the code or because it’s being used in a context that doesn’t support injection. It could also be in a third party library that you don’t have access to its source. So then lets try the next solution.

Solution 2: Wrap static call in an instance method

We can always encapsulate the call to the static method in an instance method of the class under test. Then we can easily mock or overwrite that instance method in unit tests.

Here is the same class with an instance methods that wrap actual static method call:

public class UserService < public User disableUser(long id) < User user = findUserById(id); user.setEnabled(false); saveUser(user); return user; >User findUserById(long id) < return UserDao.findUserById(id); >void saveUser(User user) < UserDao.save(user); >>

Now we can create a child of UserService in our test scope and overwrite those methods to return dummy values instead of actual database calls.

public class UserServiceTest < @Test public void disableUserTest() < UserService userService = new DummyUserService(); User sampleUser = userService.disableUser(1); assertFalse(sampleUser.isEnabled()); >class DummyUserService extends UserService < @Override User findUserById(long id) < User usr = new User(); return usr; >@Override void saveUser(User user) < // do nothing >> >

Pay attention that we create an instance of DummyUserService instead of the actual class under test.

Another variant of this solution is to mock those wrapper methods of the class instead of introducing another class. In Mockito, we can use the @Spy annotation for this purpose. With spy technique, we have an option to mock a class partially. In this case we want to mock only the findUserById and saveUser methods:

Читайте также:  Apache commons cli java

Note that mocking part of the class under test is not a good unit testing practice. But in some cases that could be the only option (at least as long as the static method is not refactored). Here is the same unit test implemented using this technique.

@RunWith(MockitoJUnitRunner.class) public class UserServiceTest < // Spying the object under test so that we can mock some methods while other methods keep their actual implementation @Spy @InjectMocks UserService userService = new UserService(); @Test public void disableUserTest() < User sampleUser = new User(); sampleUser.setEnabled(true); // Mock wrapper methods so that they would not call the actual UserDAO calls when(userService.findUserById(1)).thenReturn(sampleUser); doNothing().when(userService).saveUser(sampleUser); sampleUser = userService.disableUser(1); assertFalse(sampleUser.isEnabled()); >>

Solution 3: Mock the static methods

Not all mocking libraries support static methods mocking. It’s mainly due to its complexity or maybe because you can always use other solutions to refactor the code and make it testable. The library that I use to achieve this is PowerMock. It supports mocking for static, private, constructor and even final methods. Mocking these stuff are considered (mostly) as bad practices in unit tests and this framework should solely be used in cases that there is no other way to make a code testable. In this solution, the original code remains unchanged and everything would be handled inside the test method as below.

@RunWith(PowerMockRunner.class) // The test should be run using PowerMock runner @PrepareForTest() // We should specify the list of classes that contain static methods that we want to mock public class UserServiceTest < @InjectMocks UserService userService = new UserService(); @Before public void setup() < PowerMockito.mockStatic(UserDao.class); >@Test public void disableUserTest() < User sampleUser = new User(); sampleUser.setEnabled(true); // Mock static methods just like normal instance methods when(UserDao.findUserById(1)).thenReturn(sampleUser); sampleUser = userService.disableUser(1); assertFalse(sampleUser.isEnabled()); >>

Note that you should add the class that contains static methods in two places in your unit tests:

  • On top of the unit test class using @PrepareForTest annotation
  • In your test setup by calling the PowerMockito.mockStatic to do the necessary initialization step before trying to mock any of its methods

Conclusion

Here I tried to summerise 3 best practices to test a code that calls static methods. These are already well known for Java developers and there are obviously other solutions too. It worth mentioning that in a big project, it’s not possible to generalize a solution for all such cases. However it make sense to know what options you have and the priority of them in your team/company/project standards, so that you could obey them in both development and code review process.

Источник

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