3 回答
TA贡献1815条经验 获得超6个赞
使用严格存根(Mockito 的默认行为)when在同一方法上调用多个s 将重置该模拟。解决方案是调用when 一次并将逻辑放在一个Answer:
@BeforeEach
public void beforeEach() {
when(testClass.booleanMethod(anyBoolean())).thenAnswer(invocationOnMock -> {
if ((boolean) invocationOnMock.getArguments()[0]) {
return 1;
}
return 2;
});
}
或者,您可以使用 lenient mocking ,但这并不总是一个好主意 - lenient mocking 允许冗余存根,并使您更容易在测试中犯错误,这可能会导致“生产”代码中未被注意的错误:
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class MockitoExample {
TA贡献1804条经验 获得超8个赞
从 Mockito 2.20 开始,也可以在本地添加 lenient()
@ExtendWith(MockitoExtension.class)
public class MockitoExample {
static abstract class TestClass {
public abstract int booleanMethod(boolean arg);
}
@Mock
TestClass testClass;
@BeforeEach
public void beforeEach() {
lenient().when(testClass.booleanMethod(eq(true))).thenReturn(1);
lenient().when(testClass.booleanMethod(eq(false))).thenReturn(2);
}
@Test
public void test() {
assertEquals(1,testClass.booleanMethod(true));
assertEquals(2,testClass.booleanMethod(false));
}
}
TA贡献1998条经验 获得超6个赞
Mockito 1 和 2 没有相同的“严格”级别。
除了将 Mockito 2 与 JUnit 4 或 5 一起使用外,默认级别仍然不同。
总结 :
3个级别的严格性:
LENIENT
: 最低限度的严格WARN
: 向控制台发出额外警告STRICT_STUBS
:通过在潜在误用时抛出异常来确保干净的测试,但也可能产生一些误报。
根据使用的 API 的默认有效级别:
莫基托 1 :
LENIENT
带有 JUnit 4 的 Mockito 2:
WARN
带有 JUnit 5 (
MockitoExtension.class
) 的Mockito 2 :STRICT_STUBS
Mockito 3:计划是
STRICT_STUBS
。
更多细节
实际的 Mockito 文档对此非常清楚:
在模拟会话期间配置 Mockito 的“严格性”。会话通常映射到单个测试方法调用。Strictness 驱动更干净的测试和更好的生产力。利用增强 Strictness 的最简单方法是使用 Mockito 的 JUnit 支持(MockitoRule 或 MockitoJUnitRunner)。如果您不能使用 JUnit 支持 MockitoSession 是要走的路。
严格程度如何影响测试的行为(模拟会话)?
1.
Strictness.LENIENT
- 没有添加行为。Mockito 1.x 的默认值。仅当您不能使用 STRICT_STUBS 或 WARN 时才推荐。2.
Strictness.WARN
- 有助于保持测试清洁并提高可调试性。报告有关未使用的存根和存根参数不匹配的控制台警告(请参阅 org.mockito.quality.MockitoHint)。使用 JUnitRule 或 MockitoJUnitRunner 时 Mockito 2.x 的默认行为。如果您不能使用 STRICT_STUBS,则推荐使用。3.
Strictness.STRICT_STUBS
- 确保干净的测试,减少测试代码重复,提高可调试性。灵活性和生产力的最佳组合。强烈推荐。计划为 Mockito v3 的默认值。有关详细信息,请参阅 STRICT_STUBS。
但是无论抛出的与消息相关的异常
“具有以下不同参数的存根”
似乎是一个过于严格的检查。异常消息在某种程度上证明了这一点:
但是,当此异常生成假阴性信号时,存在合法情况:
...
被测试的代码故意使用不同的参数调用存根方法
所以默认禁止它似乎太多了。
因此,如果您使用 JUnit 5,作为STRICT_STUBS
您可以使用的替代品,WARNING
但您通常希望避免LENIENT
它太安静。
此外MockitoExtension
,该mockito-junit-jupiter
库还提供 @MockitoSettings
可在方法级别和类级别使用的 。
这是一个例子:
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@ExtendWith(MockitoExtension.class)
public class FooTest {
@MockitoSettings(strictness = Strictness.WARN)
@Test
void foo() throws Exception {
List<String> strings = Mockito.mock(List.class);
Mockito.when(strings.add("a"))
.thenReturn(true);
Mockito.when(strings.add("b"))
.thenReturn(false);
}
@Test
void fooKo() throws Exception {
List<String> strings = Mockito.mock(List.class);
Mockito.when(strings.add("a"))
.thenReturn(true);
Mockito.when(strings.add("b"))
.thenReturn(false);
}
}
fooKo()foo()成功时抛出误用 Mockito 异常但提供有用的警告:
[MockitoHint] FooTest(参见 MockitoHint 的 javadoc):
[MockitoHint] 1. 未使用 -> 在 FooTest.foo(FooTest.java:19)
[MockitoHint] 2. 未使用 -> 在 FooTest.foo(FooTest.java:21)
作为另一种选择,您还可以使用Mockito.lenient()aschoerk 很好地描述来对特定调用应用宽松的严格性。您还可以在模拟实例化时将每个模拟调用设置为宽松:
@Test
void foo() throws Exception {
List<String> strings = Mockito.mock(List.class, Mockito.withSettings()
.lenient());
....
}
添加回答
举报