Vin*_*uri 107 java junit mockito
有许多方法可以使用MockIto初始化模拟对象.这些中最好的方法是什么?
1.
public class SampleBaseTestCase {
@Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
Run Code Online (Sandbox Code Playgroud)
2.
@RunWith(MockitoJUnitRunner.class)
Run Code Online (Sandbox Code Playgroud)
[编辑] 3.
mock(XXX.class);
Run Code Online (Sandbox Code Playgroud)
建议我,如果有任何其他方法比这些更好......
gon*_*ard 132
对于模拟初始化,使用runner或者MockitoAnnotations.initMocks
是严格等效的解决方案.从MockitoJUnitRunner的javadoc :
JUnit 4.5 runner initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary. Mocks are initialized before each test method.
MockitoAnnotations.initMocks
当您已SpringJUnit4ClassRunner
在测试用例上配置了特定的运行器(例如)时,可以使用第一个解决方案(带有).
第二个解决方案(带有MockitoJUnitRunner
)是更经典和我最喜欢的.代码更简单.使用跑步者提供了框架使用自动验证的巨大优势(在本回答中由@David Wallace描述).
两种解决方案都允许在测试方法之间共享模拟(和间谍).再加上@InjectMocks
它们,它们可以非常快速地编写单元测试.样板模拟代码减少了,测试更容易阅读.例如:
@RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock(name = "database") private ArticleDatabase dbMock;
@Spy private UserProvider userProvider = new ConsumerUserProvider();
@InjectMocks private ArticleManager manager;
@Test public void shouldDoSomething() {
manager.initiateArticle();
verify(database).addListener(any(ArticleListener.class));
}
@Test public void shouldDoSomethingElse() {
manager.finishArticle();
verify(database).removeListener(any(ArticleListener.class));
}
}
Run Code Online (Sandbox Code Playgroud)
优点:代码很少
缺点:黑魔法.IMO主要是由于@InjectMocks注释.有了这个注释 "你松开了代码的痛苦"(参见@Brice的伟大评论)
第三种解决方案是在每个测试方法上创建模拟.它允许@mlk在其答案中解释为具有" 自包含测试 ".
public class ArticleManagerTest {
@Test public void shouldDoSomething() {
// given
ArticleCalculator calculator = mock(ArticleCalculator.class);
ArticleDatabase database = mock(ArticleDatabase.class);
UserProvider userProvider = spy(new ConsumerUserProvider());
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.initiateArticle();
// then
verify(database).addListener(any(ArticleListener.class));
}
@Test public void shouldDoSomethingElse() {
// given
ArticleCalculator calculator = mock(ArticleCalculator.class);
ArticleDatabase database = mock(ArticleDatabase.class);
UserProvider userProvider = spy(new ConsumerUserProvider());
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.finishArticle();
// then
verify(database).removeListener(any(ArticleListener.class));
}
}
Run Code Online (Sandbox Code Playgroud)
优点:你清楚地展示了你的api是如何工作的(BDD ...)
缺点:有更多的样板代码.(模拟创作)
我的建议是妥协.使用@Mock
注释@RunWith(MockitoJUnitRunner.class)
,但不要使用@InjectMocks
:
@RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Spy private UserProvider userProvider = new ConsumerUserProvider();
@Test public void shouldDoSomething() {
// given
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.initiateArticle();
// then
verify(database).addListener(any(ArticleListener.class));
}
@Test public void shouldDoSomethingElse() {
// given
ArticleManager manager = new ArticleManager(calculator,
userProvider,
database);
// when
manager.finishArticle();
// then
verify(database).removeListener(any(ArticleListener.class));
}
}
Run Code Online (Sandbox Code Playgroud)
优点:您清楚地演示了您的api如何工作(如何ArticleManager
实例化).没有样板代码.
缺点:测试不是自包含的,减少了代码的痛苦
Tha*_*thu 34
1. 使用 MockitoAnnotations.openMocks():
Mockito 2 中的方法MockitoAnnotations.initMock()
已弃用,并MockitoAnnotations.openMocks()
在 Mockito 3 中替换。该MockitoAnnotations.openMocks()
方法返回一个实例,AutoClosable
可用于在测试后关闭资源。下面是一个使用的示例MockitoAnnotations.openMocks()
。
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
class MyTestClass {
AutoCloseable openMocks;
@BeforeEach
void setUp() {
openMocks = MockitoAnnotations.openMocks(this);
// my setup code...
}
@Test
void myTest() {
// my test code...
}
@AfterEach
void tearDown() throws Exception {
// my tear down code...
openMocks.close();
}
}
Run Code Online (Sandbox Code Playgroud)
2.使用@ExtendWith(MockitoExtension.class):
从 JUnit5 开始@RunWith
已被删除。下面是一个使用的示例@ExtendWith
:
@ExtendWith(MockitoExtension.class)
class MyTestClass {
@BeforeEach
void setUp() {
// my setup code...
}
@Test
void myTest() {
// my test code...
}
@AfterEach
void tearDown() throws Exception {
// my tear down code...
}
}
Run Code Online (Sandbox Code Playgroud)
Jef*_*ica 24
现在(从v1.10.7开始)第四种实例化模拟的方法,即使用名为MockitoRule的JUnit4 规则.
@RunWith(JUnit4.class) // or a different runner of your choice
public class YourTest
@Rule public MockitoRule rule = MockitoJUnit.rule();
@Mock public YourMock yourMock;
@Test public void yourTestMethod() { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)
JUnit查找使用@Rule注释的TestRule的子类,并使用它们来包装Runner提供的测试语句.这样做的结果是你可以提取@Before方法,@ After方法,甚至尝试...将包装器捕获到规则中.您甚至可以在测试中与ExpectedException的方式进行交互.
MockitoRule的行为几乎与MockitoJUnitRunner完全相同,除了你可以使用任何其他运行器,例如Parameterized(它允许你的测试构造函数接受参数以便你的测试可以运行多次),或者Robolectric的测试运行器(因此它的类加载器可以提供Java替换)适用于Android原生类).这使得它在最近的JUnit和Mockito版本中使用时更加灵活.
综上所述:
Mockito.mock()
:没有注释支持或使用验证的直接调用.MockitoAnnotations.initMocks(this)
:注释支持,无使用验证.MockitoJUnitRunner
:注释支持和使用验证,但您必须使用该运行器.MockitoRule
:任何JUnit运行程序的注释支持和使用验证.另请参阅:JUnit @Rule如何工作?
有一种巧妙的方法可以做到这一点.
如果是单元测试,你可以这样做:
@RunWith(MockitoJUnitRunner.class)
public class MyUnitTest {
@Mock
private MyFirstMock myFirstMock;
@Mock
private MySecondMock mySecondMock;
@Spy
private MySpiedClass mySpiedClass = new MySpiedClass();
// It's gonna inject the 2 mocks and the spied object per reflection to this object
// The java doc of @InjectMocks explains it really well how and when it does the injection
@InjectMocks
private MyClassToTest myClassToTest;
@Test
public void testSomething() {
}
}
Run Code Online (Sandbox Code Playgroud)编辑:如果它是一个集成测试,你可以这样做(不打算用Spring的那种方式.只是展示你可以用不同的Runners初始化模拟):
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("aplicationContext.xml")
public class MyIntegrationTest {
@Mock
private MyFirstMock myFirstMock;
@Mock
private MySecondMock mySecondMock;
@Spy
private MySpiedClass mySpiedClass = new MySpiedClass();
// It's gonna inject the 2 mocks and the spied object per reflection to this object
// The java doc of @InjectMocks explains it really well how and when it does the injection
@InjectMocks
private MyClassToTest myClassToTest;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void testSomething() {
}
}
Run Code Online (Sandbox Code Playgroud)MockitoAnnotations和跑步者已经在上面讨论得很好了,所以我要把我的tuppence扔给不受爱的人:
XXX mockedXxx = mock(XXX.class);
Run Code Online (Sandbox Code Playgroud)
我使用它是因为我发现它更具描述性,而且我更喜欢(不是正确禁止)单元测试不使用成员变量,因为我喜欢我的测试(尽可能多)自包含.
JUnit 5 Jupiter 的一个小示例,删除了“RunWith”,您现在需要使用“@ExtendWith”注释来使用扩展。
@ExtendWith(MockitoExtension.class)
class FooTest {
@InjectMocks
ClassUnderTest test = new ClassUnderTest();
@Spy
SomeInject bla = new SomeInject();
}
Run Code Online (Sandbox Code Playgroud)
Mockito
该方法的最新版本MockitoAnnotations.initMocks
已被弃用
首选方式是使用
MockitoJUnitRunner
或MockitoRule
为了JUnit4
MockitoExtension
为了JUnit5
MockitoTestNGListener
为了TestNG
如果您不能使用专用的运行程序/扩展程序,您可以使用MockitoSession
归档时间: |
|
查看次数: |
171016 次 |
最近记录: |