- Mockito Cookbook
- Marcin Grzejszczak
- 616字
- 2021-07-16 11:35:02
Creating mocks of enums with PowerMock
Believe it or not, in some legacy systems you can find solutions where the business logic is implemented inside an enum. What we will discuss here is how to mock and stub (you will learn about stubbing more in Chapter 4, Stubbing Behavior of Mocks) an enum using PowerMock (since it's impossible to do it in Mockito). The PowerMock library setup has been described in the previous recipe, so we'll skip it. I will, however, repeat that the best outcome of using the PowerMock library would be to use it as a means to refactor the code, and, at the end of the day, remove the PowerMock dependency from the system since it is no longer needed.
Getting ready
Let's assume that we have the following enum containing business logic:
public enum Country implements TaxRateCalculator { POLAND { @Override public double calculateTaxFactorFor(Person person) { return new PolishWebService().doLongOperation(person); } }, OTHER { @Override public double calculateTaxFactorFor(Person person) { return new OtherWebService().doLongOperation(person); } }; public static Country fromCountryName(String countryName){ if(POLAND.name().equalsIgnoreCase(countryName)){ return POLAND; } return OTHER; } }
The system under test changes in a way that it can use the enum to perform computations. The enum is chosen based on the person's country name via the execution of the enum's fromCountry(...)
static method. Have a look at the following code:
public class TaxFactorCalculator { public static final double INVALID_TAX_FACTOR = -1; public double calculateTaxFactorFor(Person person) { Country country = Country.fromCountryName(person.getCountryName()); try { return country.calculateTaxFactorFor(person); } catch (Exception e) { System.err.printf("Exception [%s] occurred while trying to calculate tax for person [%s]%n", e, person.getName()); return INVALID_TAX_FACTOR; } } }
How to do it...
To mock an enum using PowerMock, you have to perform the following steps:
- Set up PowerMock for your test runner (please refer to the How to do it... section of the previous recipe for JUnit and TestNG).
- Mock it like any other final class, since enum is a type of a final class (please refer to the previous recipe on how to mock a final class).
The following code shows a JUnit test (for a TestNG setup, please refer to the previous recipe, Creating mocks of final classes with PowerMock) that verifies whether the system under test properly calculates the tax factor. The mockStatic(...)
method is statically imported from PowerMockito and is used for stubbing static methods. Don't worry if you don't entirely understand the concept of stubbing, because you can learn more about it in Chapter 4, Stubbing Behavior of Mocks.
As for the test itself, please remember that I'm using the BDDMockito.given(...)
and AssertJ's BDDAssertions.then(...)
static methods. Check out Chapter 7, Verifying Behavior with Object Matchers, on how to work with AssertJ or how to do the same with Hamcrest's assertThat(...)
. Have a look at the following code:
@RunWith(PowerMockRunner.class) @PrepareForTest(Country.class) public class TaxFactorCalculatorTest { static final double TAX_FACTOR = 10000; @Mock Country country; @InjectMocks TaxFactorCalculator systemUnderTest; @Test public void should_calculate_tax_factor() { // given mockStatic(Country.class); given(Country.fromCountryName(anyString())).willReturn(country); given(country.calculateTaxFactorFor(any(Person.class))).willReturn(TAX_FACTOR); // when double taxFactorForPerson = systemUnderTest.calculateTaxFactorFor(new Person()); // then then(taxFactorForPerson).isEqualTo(TAX_FACTOR); } }
How it works...
As seen in the previous example, the internals of PowerMock go far beyond the scope of this recipe, but the overall concept is such that part of the PowerMockRunner
logic is to create a custom classloader and bytecode manipulation for the classes defined using the @PrepareForTest
annotation in order to mock them and to use these mocks with the standard Mockito API. Due to bytecode manipulations, PowerMock can ignore a series of constraints of the Java language, such as extending final classes.
See also
- Refer to the PowerMock website at https://code.google.com/p/powermock/
- Refer to Chapter 8, Refactoring with Mockito, to see how to use PowerMock to refactor legacy code
- DB29forLinux,UNIX,Windows數據庫管理認證指南
- 從0到1:數據分析師養成寶典
- 數據庫開發實踐案例
- 云計算服務保障體系
- 大數據時代下的智能轉型進程精選(套裝共10冊)
- Sybase數據庫在UNIX、Windows上的實施和管理
- The Game Jam Survival Guide
- 數據科學工程實踐:用戶行為分析與建模、A/B實驗、SQLFlow
- 達夢數據庫運維實戰
- Chef Essentials
- 機器學習:實用案例解析
- Access 2010數據庫程序設計實踐教程
- 數據庫原理與設計實驗教程(MySQL版)
- Hands-On Deep Learning for Games
- 大數據隱私保護技術與治理機制研究