【发布时间】:2020-08-28 04:13:23
【问题描述】:
鉴于synchronized 和Lombok 的@Synchronized,后者在模拟被测方法时会导致NullPointerException。给定
public class Problem
{
public Problem()
{
// Expensive initialization,
// so use Mock, not Spy
}
public synchronized String a()
{
return "a";
}
@Synchronized // <-- Causes NPE during tests, literally, here
public String b()
{
return "b";
}
}
和木星测试类
class ProblemTest
{
@Mock
private Problem subject;
@BeforeEach
void setup()
{
initMocks(this);
// There is more mocking. Please don't let the simplicity
// of this example throw you off.
doCallRealMethod().when( subject ).a();
doCallRealMethod().when( subject ).b();
// This is a hack, but works. Can we rely on this?
// ReflectionTestUtils.setField( subject, "$lock", new Object[0] );
}
@Test
void a()
{
// Succeeds
assertEquals( "a", subject.a() );
}
@Test
void b()
{
// NullPointerException during tests
assertEquals( "b", subject.b() );
}
}
Lombok 添加如下内容:
private final Object $lock = new Object[0]; // We can't rely on this name
...
public String b()
{
synchronized($lock)
{
return "b";
}
}
如何模拟一个用 Lombok 的 default @Synchronized 注解修饰的方法?
这是堆栈跟踪,虽然它没有帮助。我怀疑 Lombok 在上面的示例中添加了一个字段,当然这并没有注入到模拟中,所以瞧,NPE。
java.lang.NullPointerException
at com.ericdraken.Problem.b(Problem.java:16) // <-- @Synchronized keyword
at com.ericdraken.ProblemTest.b(ProblemTest.java:43) // <-- assertEquals( "b", subject.b() );
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
... [snip] ...
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
【问题讨论】:
-
请显示异常堆栈跟踪。
-
它不会帮助你,因为它在 @Synchronized 关键字处是 NPE,但我可以将它添加到问题中。
标签: java mockito junit5 synchronized lombok