我正在努力对web服务中的方法进行单元测试。所有方法都查看注入的WebServiceContext,并从中提取userId,以确保用户获得授权。我花了很多小时试图弄清楚如何模拟WebServiceContext,但无论我尝试什么,上下文总是空的。
我的最终目标是能够返回我在测试类中指定的userId,这样我就可以继续测试该方法其余部分的实际功能。
这是大多数方法设置的精简版本:
@HandlerChain(file = "/handler.xml")
@javax.jws.WebService (...)
public class SoapImpl
{
@Resource
private WebServiceContext context;
public void methodUnderTest()
{
// context is NULL here - throws null pointer
Principal userprincipal = context.getUserPrincipal();
String userId = userprincipal.getName();
// Do some stuff - I want to test this stuff, but can't get here
}
}
这就是我试图模拟上下文并测试的方式
@RunWith(MockitoJUnitRunner.class)
@PrepareForTest(SoapImpl.class)
public class SoapImplTest {
@Mock
WebServiceContext context;
@Mock
Principal userPrincipal;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testCreateOverrideRules() {
SoapImpl testImpl = new SoapImpl();
when(context.getUserPrincipal).thenReturn(userPrincipal);
when(userPrincipal.getName()).thenReturn("testUser");
testImpl.methodUnderTest();
assertEquals(1,1);
}
}
我知道依赖注入和通过构造函数传入上下文,但我不确定在这里能不能做到这一点,因为上下文是通过@resource注释注入的。构造函数永远不会被调用。我不完全理解我将如何实现这一点。
此外,WebServiceContext和Principal是接口,因此它们不能被实例化,这使得这更加令人困惑。有人能帮我吗?我如何模拟WebServiceContext和Principal,这样我就可以跳过方法的这一部分,继续进行我真正想要测试的内容?
UPDATE我能够通过使用@InjectMocks注释来解决问题,如下代码所示:
@RunWith(MockitoJUnitRunner.class)
@PrepareForTest(SoapImpl.class)
public class SoapImplTest {
@InjectMocks
private SoapImpl testImpl = new SoapImpl();
@Mock
WebServiceContext context;
@Mock
Principal userPrincipal;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testCreateOverrideRules() {
when(context.getUserPrincipal).thenReturn(userPrincipal);
when(userPrincipal.getName()).thenReturn("testUser");
testImpl.methodUnderTest();
assertEquals(1,1);
}
}
1)您应该有一个构造函数或setter来设置测试类中的上下文。如果你不这样做,你会想添加一个正是因为这个原因。
2) 您不需要实例化WebServiceContext或Principal。只需使用Mockito.mmock(WebServiceContext.class)和Mockito.Mmock(Principal.class)为它们创建mock。然后添加Mockito.when(mockWebServiceContext)..来添加行为。
请记住,如果您正在进行单元测试,您只想测试被测方法中的逻辑,而不想测试任何其他方法或集成。这就是为什么您需要WebServiceContext和Principal的mock实例。您不希望(大概)进行集成测试。
我能够通过使用@InjectMocks
注释来解决我的问题。这使我能够将模拟对象注入到类中。以下两个资源有助于解决这一问题:
https://docs.oracle.com/javaee/6/tutorial/doc/bncjk.html
在测试期间注入@Autowired专用字段