先准备几个类,方便后面讲解:
public final class FinalSampleUtils { public static String foo() { return "aaa"; } public static String bar(String a) { return "bar:" + a; } }
这是一个final类,里面有2个static方法。
public class NewObject { public String haha() { return "haha"; } }
这是一个平淡无奇的类,没啥好说的。它俩的使用方式如下:
import org.springframework.stereotype.Service; @Service public class SampleServiceImpl implements SampleService { NewObject obj; public SampleServiceImpl() { obj = new NewObject(); } @Override public void helloWorld() { String foo = FinalSampleUtils.foo(); String bar = FinalSampleUtils.bar("test"); System.out.println("hello1:" + foo); System.out.println("hello2:" + bar); System.out.println("h:" + obj.haha()); } }
这是一个普通的@Service实现类,但有2个注意的地方:
1. 里面用到的NewObject,并不是@Autowired之类由Spring注入的,而是自己new的
2. helloWorld里,使用了final类的静态方法,以及obj的普通方法。
在3.4以下的低版本mockito中,如果想mock helloWorld方法是很困难的,但在高版本中功能有所加强,参考下面的代码:
import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.*; import org.mockito.junit.MockitoJUnitRunner; import static org.mockito.ArgumentMatchers.any; @RunWith(MockitoJUnitRunner.class) public class SampleServiceImplTest { @Mock NewObject obj; @InjectMocks SampleServiceImpl sampleService; @Test public void testHelloWorld() { MockedStatic<FinalSampleUtils> mocked = Mockito.mockStatic(FinalSampleUtils.class); //mock不带参数的static方法 mocked.when(FinalSampleUtils::foo).thenReturn("bbb"); //mock带参数的static方法 mocked.when(() -> FinalSampleUtils.bar(any())).thenReturn("xxx"); //mock代码中自己new的实例及“该实例的方法” MockedConstruction<NewObject> newObjectMocked = Mockito.mockConstruction(NewObject.class); Mockito.when(obj.haha()).thenReturn("who am i ?"); sampleService.helloWorld(); } }
跑出来的效果如下:
hello1:bbb hello2:xxx h:who am i ?
从输出上看,不管是带参还是不带参的static方法,都成功mock,返回了mock后的值,而且自己new的对象,也同样mock成功了。
关键:pom中的依赖要将mockito-core替换成mockito-inline
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>3.12.4</version> <scope>test</scope> </dependency>
注意:junit最好放在前面。