我有一个带有CDI注入字段的WicketPage,如下所示:
public class Page extends BaseWebPage {
private static final long serialVersionUID = 1L;
@Inject
private Facade facade;
public Page () {
super("Title");
}
}
我有一个单元测试,我嘲笑这个字段:
@RunWith(MockitoJUnitRunner.class)
public class PageTest{
@Mock
private Facade facadeMock;
@InjectMocks
private Page cut;
WicketTester tester = new WicketTester(new MockApplication());
@Before
public void setUp() {
Entity entity = newEntity("1", "John"));
Mockito.when(facadeMock.find()).thenReturn(entity );
}
@Test
public void testOverzicht() {
tester.startPage(cut);
//below line throws stackTrace
tester.assertRenderedPage(Page.class);
}
}
奇怪的是,Wicket无法理解我注入的Mock。在某个时刻,Wicket开始处理它的组件,其中facadeMock突然之一。然后它失败了一个组件检查的实例,因为它失败了
是一个Mockito的代理,导致Wicket抛出IllegalArgumentException。然后它继续解析,然后将facadeMock转换为它的分离方法中的Object []。下面添加了Stacktrace以澄清导致classCastException。
注意:出于隐私原因,类和包的名称会被更改。
java.lang.IllegalArgumentException: Unknown type of object facadeMock
at org.apache.wicket.MarkupContainer.getId(MarkupContainer.java:1068)
at org.apache.wicket.MarkupContainer.children_indexOf(MarkupContainer.java:1130)
at org.apache.wicket.MarkupContainer.put(MarkupContainer.java:1318)
at org.apache.wicket.MarkupContainer.add(MarkupContainer.java:175)
at nl.app.Page.onInitialize(Page.java:53)
at org.apache.wicket.Component.fireInitialize(Component.java:877)
at org.apache.wicket.MarkupContainer.internalInitialize(MarkupContainer.java:961)
at org.apache.wicket.Page.isPageStateless(Page.java:463)
at org.apache.wicket.request.handler.render.WebPageRenderer.respond(WebPageRenderer.java:244)
at org.apache.wicket.util.tester.BaseWicketTester$LastPageRecordingPageRendererProvider$1.respond(BaseWicketTester.java:2755)
at org.apache.wicket.core.request.handler.RenderPageRequestHandler.respond(RenderPageRequestHandler.java:175)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:890)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:261)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:218)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:289)
at org.apache.wicket.util.tester.BaseWicketTester.processRequest(BaseWicketTester.java:712)
at org.apache.wicket.util.tester.BaseWicketTester.processRequest(BaseWicketTester.java:651)
at org.apache.wicket.util.tester.BaseWicketTester.startPage(BaseWicketTester.java:876)
at org.apache.wicket.util.tester.BaseWicketTester.startPage(BaseWicketTester.java:893)
at nl.app.Page.testOverzicht(PageTest.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
ERROR [RequestHandlerStack.detach()] Error detaching RequestHandler
java.lang.ClassCastException: nl.app.common.facade.Facade$$EnhancerByMockitoWithCGLIB$$7b6f60ae incompatible w
ith [Ljava.lang.Object;
at java.lang.ClassCastException.<init>(ClassCastException.java:58)
at org.apache.wicket.MarkupContainer.children_size(MarkupContainer.java:1305)
at org.apache.wicket.MarkupContainer.detachChildren(MarkupContainer.java:1603)
at org.apache.wicket.Component.detach(Component.java:1186)
at org.apache.wicket.core.request.handler.PageProvider.detach(PageProvider.java:327)
at org.apache.wicket.core.request.handler.RenderPageRequestHandler.detach(RenderPageRequestHandler.java:156)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.detach(RequestCycle.java:901)
at org.apache.wicket.request.RequestHandlerStack.detach(RequestHandlerStack.java:180)
at org.apache.wicket.request.cycle.RequestCycle.onDetach(RequestCycle.java:636)
at org.apache.wicket.request.cycle.RequestCycle.detach(RequestCycle.java:589)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:293)
at org.apache.wicket.util.tester.BaseWicketTester.processRequest(BaseWicketTester.java:712)
at org.apache.wicket.util.tester.BaseWicketTester.processRequest(BaseWicketTester.java:651)
at org.apache.wicket.util.tester.BaseWicketTester.startPage(BaseWicketTester.java:876)
at org.apache.wicket.util.tester.BaseWicketTester.startPage(BaseWicketTester.java:893)
at nl.app.Page.testOverzicht(PageTest.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
答案 0 :(得分:0)
我将建议一种稍微不同的方法,它不会使用@InjectMocks
。
从CDI的角度来看,实现一个bean在测试(模拟)和实际场景(完全实现)中使用不同实现的行为的方法是使用 @Alternative
。它允许像嘲笑那样做,但是......没有嘲笑任何东西。 CDI spec本身在嘲弄的背景下谈到了替代方案。
它的工作方式如下。首先,您的bean具有真正的实现:
public MyBean {
public void awesomeMethod() {
doStuff(); //do what you really want and or need here
}
}
现在有另一个@Alternative
bean扩展你的bean:
@Alternative
public MyMockedBean extends MyBean {
public void awesomeMethod() {
// do some other, (mocked) stuff here, or don't do anything at all
}
}
现在,最后但并非最不重要的是,默认情况下 @Alternative
已停用。这意味着CDI通常会忽略它并使用原始bean代替。为了启用它,您可以使用两种方法:
@Priority
,可以随时全局启用它。在你的情况下你不希望这样。beans.xml
,或者更为明确的是,在beans.xml
中列出替代方案。这样就可以在每个bean存档的基础上启用替代方案。这是要走的路 - 只需在测试中添加不同的beans.xml
并在那里列出@Alternative
。这样,您将保留标准behvaiour超出测试范围,并在测试中使用“模拟”bean。 beans.xml
应包含以下行,以便启用@Alternative
:
<alternatives>
<class>com.whatever.MyMockedBean</class>
</alternatives>