简体   繁体   English

如何在 Wiremock Servlet 上启用响应模板?

[英]How to enable Response Templating on a Wiremock Servlet?

I am running Wiremock on a servlet implementing this project from https://github.com/tomakehurst/wiremock/tree/master/sample-war我正在从https://github.com/tomakehurst/wiremock/tree/master/sample-war实现这个项目的 servlet 上运行 Wiremock

I am able to deploy this into a Tomcat and its working.我能够将其部署到 Tomcat 中并使其正常工作。

Now, I want to enable Response Templating on this server so that I can use handlebar templates to tweak the response body.现在,我想在此服务器上启用响应模板,以便我可以使用车把模板来调整响应正文。 I saw a few solutions related to Junit rules, directly setting this up from the code and also from standalone server but can't find a solution to enable response templating from a servlet.我看到了一些与 Junit 规则相关的解决方案, 直接从代码和独立服务器进行设置,但找不到从 servlet 启用响应模板的解决方案。

How do I enable this from a wiremock servlet?如何从wiremock servlet 启用此功能?

If you would like to use wiremock with docker, I have a sample docker-compose.yaml here with verbose logging and templating.如果你想在 docker 中使用 wiremock,我这里有一个示例 docker-compose.yaml,其中包含详细的日志记录和模板。

Spin up Wiremock in a docker container with docker-compose up.使用 docker-compose up 在 docker 容器中启动 Wiremock。

docker-compose.yaml sample: docker-compose.yaml 示例:

version: "3"
services:
 wiremock:
  image: rodolpheche/wiremock:latest
  ports:
    - "8181:8080"
  volumes:
    - ./__files/:/./home/wiremock/__files/
    - ./mappings/:/./home/wiremock/mappings/
  command:
    - -verbose
    - -global-response-templating

docker-compose up (in the directory you saved the yaml, and accept the requests for filesystem access) then you should be ready to go. docker-compose up(在您保存 yaml 的目录中,并接受文件系统访问请求)然后您应该准备好了。

Wiremock url would be http://localhost:8181 Wiremock url 将是http://localhost:8181

After that do a recording with real data ( http://localhost:8181/__admin/recorder )之后使用真实数据进行记录( http://localhost:8181/__admin/recorder

Split the body to a separate file and place it in the __files folder.将正文拆分为单独的文件并将其放在 __files 文件夹中。 Point to the file with ""bodyFileName" in the request file (mappings)指向请求文件中带有“bodyFileName”的文件(映射)

I have some suggestions here.我在这里有一些建议。 mobileera_wiremock_kb mobileera_wiremock_kb

Okay finally i found the answer, You need to create your custom listner extending ServletContextListener and then programatically set the response templates.好的,我终于找到了答案,您需要创建扩展 ServletContextListener 的自定义侦听器,然后以编程方式设置响应模板。

public class CustomListener implements ServletContextListener {

private static final String APP_CONTEXT_KEY = "WireMockApp";

@Override
public void contextInitialized(ServletContextEvent sce) {
    ServletContext context = sce.getServletContext();

    boolean verboseLoggingEnabled = Boolean.parseBoolean(
            firstNonNull(context.getInitParameter("verboseLoggingEnabled"), "true"));
    WarConfiguration warConfiguration = new WarConfiguration(context);
    warConfiguration.extensionsOfType(MockTokenTemplate.class);
    final WireMockConfiguration wireMockConfiguration =WireMockConfiguration.wireMockConfig();
    wireMockConfiguration.extensions("com.test.MockTokenTemplate","com.test.MockTokenInqTemplate");
    //wireMockConfiguration.jettySettings();
    wireMockConfiguration.containerThreads(Integer.valueOf(200));
    wireMockConfiguration.disableRequestJournal()
            .containerThreads(Integer.valueOf(200))
            .jettyAcceptors(Integer.valueOf(-1))
            .jettyAcceptQueueSize(Integer.valueOf(1000))
            .jettyHeaderBufferSize(Integer.valueOf(8192));
    String fileSourceRoot = context.getInitParameter("WireMockFileSourceRoot");
 final FileSource fileSource = new ServletContextFileSource(context, fileSourceRoot);
    wireMockConfiguration.fileSource(fileSource);
    //wireMockConfiguration.usingFilesUnderDirectory("/WEB-INF/wiremock/");

    //wireMockConfiguration =(WireMockConfiguration) warConfiguration;
    WireMockApp wireMockApp = new WireMockApp(wireMockConfiguration, new NotImplementedContainer());
    context.setAttribute(APP_CONTEXT_KEY, wireMockApp);
    context.setAttribute(StubRequestHandler.class.getName(), wireMockApp.buildStubRequestHandler());
    context.setAttribute(AdminRequestHandler.class.getName(), wireMockApp.buildAdminRequestHandler());
    context.setAttribute(Notifier.KEY, new Slf4jNotifier(verboseLoggingEnabled));
}

/**
 * @param context Servlet context for parameter reading
 * @return Maximum number of entries or absent
 */
private Optional<Integer> readMaxRequestJournalEntries(ServletContext context) {
    String str = context.getInitParameter("maxRequestJournalEntries");
    if(str == null) {
        return Optional.absent();
    }
    return Optional.of(Integer.parseInt(str));
}

@Override
public void contextDestroyed(ServletContextEvent sce) {
}

} }

Let me know if you need help in creating custom response templates.如果您在创建自定义响应模板方面需要帮助,请告诉我。

I handled adding definitionTransformer to ServletListener by extending and overriding the WireMockWebContextListener我通过扩展和覆盖WireMockWebContextListener处理将definitionTransformer添加到ServletListener

This keeps the configuration stock as much as possible and uses Spring features to auto-register new Transformers without any other config change.这会尽可能地保留配置库存,并使用 Spring 功能自动注册新的Transformer,而无需更改任何其他配置。 Using latest wiremock artifact 2.26.3使用最新的wiremock artifact 2.26.3

Below is complete setup config and implementation.下面是完整的设置配置和实现。

public abstract class AbstractResponseDefinitionTransformer extends ResponseDefinitionTransformer implements Extension {

    @Override
    public String getName() {

    return WordUtils.uncapitalize(getClass().getSimpleName());
    }
}

@Component
public class CustomResponseDefinitionTransformer extends AbstractResponseDefinitionTransformer {

    @Override
    public ResponseDefinition transform(Request request, ResponseDefinition responseDefinition, FileSource files,
                                        Parameters parameters) {

        System.out.println("Hello World !!!");

        return responseDefinition;
    }
}

public class CustomWireMockWebContextListener extends WireMockWebContextListener {

    private static final String APP_CONTEXT_KEY = "WireMockApp";

    private final List<? extends AbstractResponseDefinitionTransformer> abstractResponseDefinitionTransformers;

    public CustomWireMockWebContextListener() {
        this(Collections.emptyList());
    }

    public CustomWireMockWebContextListener(
            List<? extends AbstractResponseDefinitionTransformer> abstractResponseDefinitionTransformers) {
        this.abstractResponseDefinitionTransformers = abstractResponseDefinitionTransformers;
    }

        @Override
        public void contextInitialized(ServletContextEvent sce) {

            super.contextInitialized(sce);

            final ServletContext context = sce.getServletContext();

            final WarConfiguration warConfiguration = buildCustomWarConfiguration(context);
            final WireMockApp wireMockApp = new WireMockApp(warConfiguration, new NotImplementedContainer());

            context.setAttribute(APP_CONTEXT_KEY, wireMockApp);
            context.setAttribute(StubRequestHandler.class.getName(), wireMockApp.buildStubRequestHandler());
            context.setAttribute(AdminRequestHandler.class.getName(), wireMockApp.buildAdminRequestHandler());
        }

        private WarConfiguration buildCustomWarConfiguration(final ServletContext context) {

            final Map<String, Extension> map = abstractResponseDefinitionTransformers.stream()
                    .collect(Collectors.toMap(AbstractResponseDefinitionTransformer::getName, transformer -> transformer));

            return new WarConfiguration(context) {
                @Override
                public <T extends Extension> Map<String, T> extensionsOfType(Class<T> extensionType) {

                    return (Map<String, T>) Maps.filterEntries(map, valueAssignableFrom(extensionType));
                }
            };
        }
}

@Configuration
public class WireMockConfiguration {

    @Autowired
    private List<? extends AbstractResponseDefinitionTransformer> abstractResponseDefinitionTransformers;

    @Bean
    public ServletListenerRegistrationBean wireMockWebContextListener() {
        final ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
        bean.setEnabled(true);
        bean.setListener(new CustomWireMockWebContextListener(abstractResponseDefinitionTransformers));
        return bean;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM