如何模拟注入Web Service的WebServiceContext

时间:2017-11-16 22:39:54

标签: java web-services unit-testing junit mockito

我正在努力对我的网络服务中的方法进行单元测试。所有方法都会查看注入的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,以便我可以通过该方法的这一部分,继续我真正想要测试的内容?

更新 我能够通过使用@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);
    }

}

2 个答案:

答案 0 :(得分:0)

1)你应该有一个构造函数或setter来设置你所测试的类中的上下文。如果你不这样做,你会因为这个原因而添加一个。

2)您不需要实例化WebServiceContext或Principal。只需使用Mockito.mock(WebServiceContext.class)和Mockito.mock(Principal.class)为它们创建模拟。然后添加Mockito.when(mockWebServiceContext)..来添加行为。

请记住,如果您正在进行单元测试,则只想测试测试方法中的逻辑,而不测试任何其他方法或集成。这就是您想要WebServiceContext和Principal的模拟实例的原因。你不想进行集成测试(大概)。

答案 1 :(得分:0)

我能够使用@InjectMocks注释来解决我的问题。这允许我将我的模拟对象注入到类中。以下两个资源有助于解决这个问题:

https://docs.oracle.com/javaee/6/tutorial/doc/bncjk.html

Injecting @Autowired private field during testing