Java Spring Security@WithMockUser不适用于cucumber测试
我使用cucumber测试来测试启用了spring安全性的spring boot应用程序。除了使用cucumber测试运行我的测试套件外,一切正常。一些使用spring安全性的测试例如Java Spring Security@WithMockUser不适用于cucumber测试,java,spring,spring-security,Java,Spring,Spring Security,我使用cucumber测试来测试启用了spring安全性的spring boot应用程序。除了使用cucumber测试运行我的测试套件外,一切正常。一些使用spring安全性的测试例如 @WithMockUser(username = "BROWSER", roles = {"BROWSER","ADMIN"}) 失败。如果我将这些测试作为简单的junit测试在隔离状态下运行,那么它们确实可以工作,但在使用cucumber测试步骤运行时失败。 当我对cucumber测试运行相同的
@WithMockUser(username = "BROWSER", roles =
{"BROWSER","ADMIN"})
失败。如果我将这些测试作为简单的junit测试在隔离状态下运行,那么它们确实可以工作,但在使用cucumber测试步骤运行时失败。
当我对cucumber测试运行相同的测试时,问题看起来好像没有应用spring安全测试模拟行为
我的Cumber试运行课程如下
@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources", monochrome = true, format =
{"pretty", "html:src/main/resources/static/cucumber"})
public class CucumberTests
{
}
我还注意到,通过Maven以false
运行时也可以使用相同的方法。如果未选中此选项,Maven触发的测试用例运行也会失败
更新
AbstractIntegrationTest类所有测试都将扩展
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Services.class,loader = SpringApplicationContextLoader.class)
//@IntegrationTest
@WebIntegrationTest(randomPort = true)
public abstract class AbstractIntegrationTest {
另一个不起作用的用例是使用这些注释的特性条件,如下所示
@When("^I apply a GET on (.*)$")
@WithMockUser(username = "BROWSER", roles = { "BROWSER", "ADMIN" })
public void i_search_with_rsql(String query) throws Throwable {
result = mvc.perform(get(uri, query));
}
这方面的任何帮助或解决方法。根据您的评论,您需要确保应用Spring安全性。您可以在参考文档的中找到这方面的示例:
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
// ...
@Before
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity()) // ADD THIS!
.build();
}
WithMockUser
不适用于Cucumber。用黄瓜钩代替
WithMockUser
依赖于Spring的测试上下文支持中的TestExecutionListener#beforeTestMethod
,但在运行Cucumber runner时不会调用它们。这是因为Cucumber运行由步骤组成的场景,而不是标准的JUnit测试方法
选项1-安全上下文挂钩。您可以使用挂钩设置安全上下文,例如:
@ActiveProfiles("test")
@SpringBootTest(classes = MyServer.class)
@AutoConfigureMockMvc
@AutoConfigureRestDocs
@AutoConfigureCache
public class MyServerContextHooks {
@Before
public void onBeforeScenario(final Scenario scenario) {
// This method does nothing - context setup is done with annotations
}
}
场景注释示例:
@WithAdminUser
Scenario: Run action as admin
...
public class TestUserHooks {
@Before("@WithAdminUser")
public void setupAdminUser() {
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(
"admin",
"N/A",
createAuthorityList("admin")));
}
}
在场景中使用注释的示例钩子:
@WithAdminUser
Scenario: Run action as admin
...
public class TestUserHooks {
@Before("@WithAdminUser")
public void setupAdminUser() {
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(
"admin",
"N/A",
createAuthorityList("admin")));
}
}
选项2-身份验证步骤。另一种方法是使用特殊步骤将用户提供到mockMvc中:
Scenario: Run action as admin
Given I am logged in as admin
...
步骤定义示例:
public class SecurityTestSteps {
@Autowired
private MockMvcGlue mockMvc;
@Autowired
private OAuth2Mocks oauth2Mocks;
@Autowired
private TestUsers users;
/**
* Provides a one of predefined role-based authentications for the current request.
*/
@Given("^I am logged in as (admin|editor|user)$")
public void given_UserIsAuthenticatedWithRole(final String role) {
switch (role) {
case "admin":
mockMvc.request().with(authentication(oauth2Mocks.auth(users.admin())));
break;
case "editor":
mockMvc.request().with(authentication(oauth2Mocks.auth(users.edtior())));
break;
default:
throw new CucumberException("Unsupported role <" + role + ">");
}
}
}
public类SecurityTestSteps{
@自动连线
私有MockMvcGlue mockMvc;
@自动连线
私有OAuth2Mocks OAuth2Mocks;
@自动连线
私人测试用户;
/**
*为当前请求提供预定义的基于角色的身份验证之一。
*/
@给定(^I以(管理员|编辑|用户)$身份登录)
public void给定_UserIsAuthenticatedWithRole(最终字符串角色){
交换机(角色){
案例“管理”:
mockMvc.request().with(身份验证(oauth2Mocks.auth(users.admin()));
打破
案例“编辑”:
mockMvc.request().with(身份验证(oauth2Mocks.auth(users.edtior()));
打破
违约:
抛出新CucumberException(“不支持的角色”);
}
}
}
要让WithMockUser工作,Spring安全应用程序必须在与测试相同的进程/线程上运行。是这样吗?@Robja让我检查一下,当我运行我应用程序中的所有测试时,没有Cucumber,这些测试运行正常。是Cucumber测试运行使我的测试单独运行吗。已使用ABstractIntegrationTest类更新了我的问题摘要。我的所有测试用例都是从中继承的。@RobWinch是否有withMockUser的替代方案来模拟,因为如果您将then-in用于cucumber测试,则这些选项似乎也不起作用@当(^I应用GET-on(.*)$)@withMockUser(username=“BROWSER”,roles={“BROWSER”,“ADMIN”})public void i_search_with_rsql(字符串查询)抛出可丢弃的{result=mvc.perform(get(uri,query))}
如何设置MockMvc实例(即mvc变量)?@RobWinch目前我正在使用cucumber@Before注释@cumber.api.java.Before public void setUp(){this.mvc=MockMvcBuilders.webAppContextSetup(context.build();}
我想上面的方法适用于模拟springsecuritychain,但现在我必须将模拟角色作为mvc.perform(get(uri,query).with(getAdminRole())放入get请求中
虽然注释@WithMockUser仍然不起作用,但无论如何,我已经找到了一个解决方法,并且测试通过了:)谢谢