Mockito 3.4.0
mock常见静态方法
待测试类:
package com.taobao.vip.shop.biz.sqyk.manager;
import com.taobao.vip.shop.biz.sqyk.util.TairUtil;
/**
* Created by yitian.zyt on 2021/6/30
*/
@Slf4j
@Component
public class SqykChannelBenefitManager {
public static final int BLACK_USER_TAIR_NAME_SPACE = 132;
@Resource
private TairManager blackUserTairManager;
/**
* 判断红包发放是否缓存记录
* @param tairKey 缓存key
* @return 有记录返回true,无记录返回false
*/
public boolean isInWinPeriod(String tairKey) {
String value = TairUtil.get(blackUserTairManager, BLACK_USER_TAIR_NAME_SPACE, tairKey);
return StringUtils.isNotEmpty(value);
}
}
测试方法:
package com.taobao.vip.shop.biz.sqyk.manager;
/**
* Created by yitian.zyt on 2021/7/6
*/
@RunWith(MockitoJUnitRunner.class)
public class SqykChannelBenefitManagerTest extends TestCase {
@InjectMocks
private SqykChannelBenefitManager sqykChannelBenefitManager;
@Mock
private TairManager blackUserTairManager;
@Before
public void setup() throws NoSuchFieldException, IllegalAccessException {
MockitoAnnotations.openMocks(this);
}
/**
* isInWinPeriod
*/
@Test
public void isInWinPeriod_normalTest() {
try (MockedStatic<TairUtil> theMock = Mockito.mockStatic(TairUtil.class)) {
theMock.when(() -> TairUtil.get(blackUserTairManager, 132, "key")).thenReturn("hadWin");
boolean res = sqykChannelBenefitManager.isInWinPeriod("key");
Assert.assertTrue(res);
}
}
@Test
public void isInWinPeriod_nullTest() {
try (MockedStatic<TairUtil> theMock = Mockito.mockStatic(TairUtil.class)) {
theMock.when(() -> TairUtil.get(blackUserTairManager, 132, "key")).thenReturn(null);
boolean res = sqykChannelBenefitManager.isInWinPeriod("key");
Assert.assertFalse(res);
}
}
}
注意:上面TairUtil方法调用时传入的具体参数值,也可以使用Mockito.any形式进行替换。如果设置了具体参数,则仅能对具体参数的执行过程进行mock。
PowerMock
mock静态方法(带static代码块的类):
- PowerMock 抑制运行静态块:PowerMock 抑制运行静态块_千里之行始于足下-CSDN博客_powermock 抑制
- ProwerMock mock静态方法时,when...doReturn存在的bug:Static mocking broken for Mockito >= 2.26.1 · Issue #992 · powermock/powermock · GitHub
- bug使用when...doAnswer解决:android - org.mockito.exceptions.misusing.NotAMockException: Argument should be a mock, but is: class java.lang.Class for Andriod SSLContext.getInstance() metho - Stack Overflow
待测试类:
package com.taobao.vip.shop.biz.sqyk.domain.packageshow;
public class SqykPackageShowConfig {
/**
* 通用配置
*/
private static Properties commonProperties;
/**
* 卡类别 -> 卡下所有权益
*/
private static Map<String, List<SqykBenefitInfoWithClass>> cardClassIndex = Maps.newHashMap();
// 类中存在静态代码块
static {
DiamondUtils.subscribe(BENEFIT_DATA_ID, GROUP_ID, x -> {
if (StringUtils.isBlank(x)) {
benefits = Lists.newArrayList();
} else {
benefits = JSON.parseArray(x, SqykBenefitInfoWithClass.class);
buildIndex(benefits);
}
});
DiamondUtils.subscribeByProperties(COMMON_DATA_ID, GROUP_ID, x -> {
if (x == null) {
commonProperties = new Properties();
} else {
commonProperties = x;
}
});
}
// 待测试静态方法
public static List<SqykBenefitInfoWithClass> getBenefitsByCardClass(String cardClass) {
List<SqykBenefitInfoWithClass> result = cardClassIndex.get(cardClass);
return result == null ? new ArrayList<>(0) : result;
}
}
测试方法:
package com.taobao.vip.shop.biz.sqyk.packageBenefit;
@RunWith(PowerMockRunner.class)
@PrepareForTest({SqykPackageShowConfig.class})
@SuppressStaticInitializationFor("com.taobao.vip.shop.biz.sqyk.domain.packageshow.SqykPackageShowConfig")
public class PackageBenefitOnActionCheckHandlerTest {
private static final Long mockUserId=2210634737969L;
private static final String mockLifeCycle="20210826-20210925";
private static final String mockPackageName="crowd_pinHigh_taoLow_V6";
private static final String mockBenefitCode="532e17d03653424893697dce7a60a21fxxxxxxx";
private static final Long mockIssueRecordId= 12345678L;
private static final String mockStrategyCode="42aff94fff074f3099836e0c844b25b0xxxxx";
@Before
public void setup() {
MockitoAnnotations.openMocks(this);
}
@Test
public void mockSqykPackageShowConfigGetBenefitsByCardClass(){
List<SqykBenefitInfoWithClass> list = Lists.newArrayList();
SqykBenefitInfoWithClass sqykBenefitInfoWithClass = new SqykBenefitInfoWithClass();
sqykBenefitInfoWithClass.setBenefitCode(mockBenefitCode);
sqykBenefitInfoWithClass.setBenefitClass("highValue");
sqykBenefitInfoWithClass.setCardClass(mockPackageName);
sqykBenefitInfoWithClass.setStrategyCode(mockStrategyCode);
list.add(sqykBenefitInfoWithClass);
// mockito无法mock带有static静态方法块的类
// try (MockedStatic<SqykPackageShowConfig> theMock = Mockito.mockStatic(SqykPackageShowConfig.class)) {
// theMock.when(()->SqykPackageShowConfig.getBenefitsByCardClass(mockPackageName)).thenReturn(list);
// }
/*
这里使用powermockito的如下方式有个bug:https://github.com/powermock/powermock/issues/992
PowerMockito.when(SqykPackageShowConfig.getBenefitsByCardClass(mockPackageName)).thenReturn(list);
需要使用when...thenAnswer的方式
*/
PowerMockito.mockStatic(SqykPackageShowConfig.class);
PowerMockito.when(SqykPackageShowConfig.getBenefitsByCardClass(mockPackageName)).thenAnswer(t -> list);
List<SqykBenefitInfoWithClass> resultList = SqykPackageShowConfig.getBenefitsByCardClass(mockPackageName);
Assert.assertNotNull(resultList);
}
}