Open pun-ky opened 4 years ago
You can try proxy API in current version, which can load any URL as response.
Tell me if it works for you.
you didn't get me ;)
I'd like to implement sth like that
server.request(by("foo")).response(jsonFileInJcr("/etc/stubs/foo-response.json");
any hints appreciated
I don't want to access that using URL / HTTP and any other protocol. My JCR storage is a same OSGi container / Moco is running at same server as JCR - I have programmatic access to read that data from JCR so using HTTP is not an option (overhead).
So, what you want is an interface to allow you extend to access your content, isn't it?
BTW, is JCR Content repository API for Java?
yep, yep :)
that repo looks like this:
I am implementing a tool that allows writing stub scripts that are configuring Moco HTTP server. I'd like to be able to easily respond content just read from the repository (not always a same string, but content from file stored in a repository that may change in the meantime)
hmm in other words... I am asking for .. maybe there is sth like response(Supplier<String>)
?
No such interface for now, but it's not hard to support.
I can provide the interfaces like the following:
text(Supplier<Object>);
text(Function<Request, Object>);
json(Supplier<Object>);
json(Function<Request, Object>);
so, you can write your API like this:
server.request(...).response(json(() -> new YourPojo());
server.request(...).response(json((request) -> new YourPojo());
It would be nice 🙂
What if I have no Pojo class and want to supply json string read from repo file?
how about a supplier for template variables? snippet in Groovy that I would like to support:
stubs.server
.get(by(uri("/current-date")))
.response(template('Today date is "${date}"', "date", dynamicVar({ new Date() })))
I implemented it as :
public final class DynamicExtractor<T> implements RequestExtractor<T> {
private final Supplier<T> objectSupplier;
public DynamicExtractor(final Supplier<T> objectSupplier) {
this.objectSupplier = objectSupplier;
}
@Override
public Optional<T> extract(final Request request) {
return of(objectSupplier.get());
}
}
public final class MocoExtensions {
public static RequestExtractor<Object> dynamicVar(final Supplier<Object> textSupplier) {
return new DynamicExtractor<>(checkNotNull(textSupplier, "Template variable supplier should not be null or empty"));
}
}
and it works.
my doubt is only about Optional.of()
vs Optional.ofNullable
. In PlainExtractor
there is of
but I can imagine returning nulls sometimes and maybe ofNullable
in both PlainExtractor
and DynamicExtractor
would be better.
btw why ImmutableMap
is in template()
method signature, maybe it would be better to make it immutable just after calling method acceptingMap<String, RequestExtractor<?>>
to make it more universal / more nicely callable e.g from my Groovy scripts.. ;)
Cool, really good suggestion!
var
for template
is also a place which works for you. But template is just for specific scenario, so I can support both template
and response
.
Any ETA for release with improvements? 🙂
@pun-ky
The json
and var
have been committed to the codebase.
You can run ./gradlew build
to build your own JAR.
Cool. I will test it for sure and let you know if it's okay 🙂
https://github.com/dreamhead/moco/commit/40d2cb88b6531e41775599bc7a91d0a96deaadaf
@dreamhead, potentially, I would like to create mocks not only for JSON files but also for text, XML, INI... almost any type of file (there should be no limitation type-based) and load them from the repository / be also supplied by function.
How would you address that case? I see that you implemented a JSON support only as requested originally in the issue, but to be honest, I was expecting sth more general.
@dreamhead , in other words, I'd like to address sth like below:
server.response(with(text(() -> jcrRepository.readFileAsString("/some/node/my-response.xml"))), header("Content-Type", "application/xml"));
server.response(with(text(() -> jcrRepository.readFileAsStream("/some/node/logs/my.log")));
server.response(with(binary(() -> jcrRepository.readFileAsStream("/some/node/reports/sample-report.pdf"))), header("Content-Type", "application/pdf"));
It would be nice if that function returning stream will output response without redundantly allocating whole PDF (potentially big) in memory... or same case for mocking bigger log file
also, a supplier should be able to return a string in some cases because some external API could not return streams but strings... and it will be just easier to glue Moco with external API in that way (mock could be implemented more quickly)
about added overloaded signatures... there is a problem when using them from Groovy
groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method com.cognifide.aem.stubs.moco.Moco#var.
Cannot resolve which method to invoke for [class Script1$_run_closure1] due to overlapping prototypes between:
[interface java.util.function.Function]
[interface java.util.function.Supplier]
instead of simply:
stubs.server
.get(by(uri("/current-date")))
.response(template('Today date is "${date}"', "date", var({ new Date() })))
I need to write:
stubs.server
.get(by(uri("/current-date")))
.response(template('Today date is "${date}"', "date", var(new java.util.function.Supplier<Object>() {
@Override
public Object get () {
return new Date()
}
}
)))
any suggestions on how to implement loading JSON files from JCR instead of the filesystem will be appreciated.
I am implementing a tool for Adobe Experience Manager which will be based on Moco which will run on OSGi. Yes it is possible (there is a little problem with Guava which you are using but nvm). On AEM, all assets are just stored on JCR, so that's the only way to go. In Wiremock, I have seen
FileSource
interface, which seems that supports abstraction for loading JSONs from any sources. I hope that Moco is having sth like this too.