Mock CompletableFuture in spock - java

i trying create stub or mock for CompletableFuture in spock. My method is called async and return CompletableFuture. In spock method always return null. What's wrong?
public class ProductFactory() {
#Autowired
ProductRepository repository;
public Product create(String name) {
this.checkProductExists(name);
}
public CompletableFuture<Boolean> checkProductExists(String name) {
//call repository and return
boolean result = this.repository.checkProductExists(name);
return CompletableFuture.completedFuture(result)
}
}
class ProductFactorySpec extends Specification {
ProductRepository repository = Mock(ProductRepository)
ProductFactory factory = new ProductFactory(repository)
def "When i decide create new product"() {
def future = CompletableFuture.completedFuture(true)
when:
repository.checkProductExists("Fake string") >> future
future.get() >> true
def result = this.factory.create(fakeOfferData())
then:
result instanceof Product
}
}
Update code, it's was not completed.

items.checkProductExists("Fake string") >> future: items is not defined, did you mean factory?
boolean result = this.repository.checkProductExists(name); this line doesn't expect a future, so why are you trying to return one
future.get() >> true you created a real CompletableFuture so stubbing is not possible
All stubbing should be performed outside of the when block in the given/setup block
Your create doesn't return a Product
From the code you have provided:
class ProductFactorySpec extends Specification {
ProductRepository repository = Stub()
ProductFactory factory = new ProductFactory(repository)
def "When i decide create new product"() {
given:
repository.checkProductExists(_) >> true
when:
def result = factory.create("fakeProduct")
then:
result instanceof Product
}
}

You can force to complete the future using future.complete(true)
def "When i decide create new product"() {
def future = new CompletableFuture<Boolean>()
when:
repository.checkProductExists("Fake string") >> future
future.complete(true)
def result = this.factory.create(fakeOfferData())
then:
result instanceof Product
}

Related

Using Spock/Groovy to test a Java method that extends HashMap - how to mock HashMap get method?

In our codebase, we use a specific class map which stores the results for authorization requests including whether or not someone has the auth to get in.
Currently writing some unit tests (a thing I have little practice on) that contains this, a modified version of our code for you to look at:
public class TestResultMap extends HashMap<String, TestResult> {
private static final long serial = -1234567890L;
public boolean isAuthorized(String resource) {
TestResult result = get(resource);
if (result == null) {
throw new RunExcept("Authorization not calculated");
}
return result.isAuthorized();
}
}
When testing the isAuthorized() in the groovy file I had made, I've noticed that no matter how I have it arranged, I can not get it to instantiate TestResult result = get(resource) to be anything other than null. isAuthorized() calls upon an enum method in another class that contains the possibilities, but otherwise just returns a boolean.
That's tangential to the point, though. Is there an efficient way to mock this or force get(resource) to output something not null? Alternatively, can I directly set result to a particular value?
Thanks for any help. Incredibly new to this whole process and documentation has been tricky.
I am showing you
how to stub the result of TestResult.isAuthorized to always return true or false,
how to use a spy on a real TestResultMap instance in order to stub the result of get(_) with the rest of the class behaving normally (partial mocking),
how to test your class without using any mocks, because if the methods used in the test are not doing anything expensive, mocking might not be necessary at all. Or maybe you want to also have an integration test in addition to the unit test with mocked dependencies.
Classes under test:
package de.scrum_master.stackoverflow.q70149644;
public class TestResult {
private String result;
public TestResult(String result) {
this.result = result;
}
public boolean isAuthorized() {
return !result.toLowerCase().matches(".*(forbidden|blocked|unauthorized|denied).*");
}
#Override
public String toString() {
return "TestResult(result='" + result + "')";
}
}
package de.scrum_master.stackoverflow.q70149644;
import java.util.HashMap;
public class TestResultMap extends HashMap<String, TestResult> {
private static final long serial = -1234567890L;
public boolean isAuthorized(String resource) {
TestResult result = get(resource);
if (result == null) {
throw new RuntimeException("Authorization not calculated");
}
return result.isAuthorized();
}
}
Spock specification:
package de.scrum_master.stackoverflow.q70149644
import spock.lang.Specification
class TestResultMapTest extends Specification {
def "resource is authorized"() {
given:
TestResultMap map = new TestResultMap()
TestResult testResult = Stub() {
isAuthorized() >> true
}
map.put("resource", testResult)
expect:
map.isAuthorized("resource")
}
def "resource is unauthorized"() {
given:
TestResultMap map = new TestResultMap()
TestResult testResult = Stub() {
isAuthorized() >> false
}
map.put("resource", testResult)
expect:
!map.isAuthorized("resource")
}
def "resource not found"() {
given:
TestResultMap map = Spy() {
get(_) >> null
}
when:
map.isAuthorized("resource")
then:
def rte = thrown RuntimeException
rte.message == "Authorization not calculated"
}
def "test without mocks"() {
given:
TestResultMap map = new TestResultMap()
map.put("OK", new TestResult("Hello world"))
map.put("not OK", new TestResult("Access denied"))
expect:
map.isAuthorized("OK")
!map.isAuthorized("not OK")
when:
map.isAuthorized("foo")
then:
def rte = thrown RuntimeException
rte.message == "Authorization not calculated"
}
}

How does java lambdas external references work?

I'm wondering how does lambdas external references work. Let me explain:
Suppose i have this supplier implementation and this model class :
public class TestSupplierImpl implements Supplier<Boolean> {
public Predicate<Integer> predicate;
public TestSupplierModel model;
public TestSupplierImpl() {
this.predicate = i -> model.something.equals(i);
}
#Override
public Boolean get() {
return predicate.test(3);
}
}
class TestSupplierModel {
public Integer something;
public TestSupplierModel(Integer something) {
this.something = something;
}
}
Then i execute the following code:
TestSupplierImpl test = new TestSupplierImpl(); // line 1
test.model = new TestSupplierModel(3); // line 2
Boolean resultado = test.get(); // line 3
Line 1: creating a new instance of TestSupplierImpl. This new instance's predicate has a null reference of model. This makes sense because at the moment of creation of the predicate, model reference is null.
Line 2: assign to variable model a new instance of TestSupplierModel.
Line 3: test.predicate now has model reference with the new assigned value. Why is this ?
I don't understand why ,when I changed model reference, the predicate updates its model reference to the new one. How is that ?
Thanks in advance !
Does it make sense if you rewrote your TestSupplierImpl() constructor as follows?
public Predicate<Integer> predicate;
public TestSupplierModel model;
public TestSupplierImpl() {
// same effect as this.predicate = i -> model.something.equals(i);
this.predicate = new Predicate<Integer>() {
public boolean test(Integer i) {
return model.something.equals(i);
}
};
}
#Override
public Boolean get() {
return predicate.test(3);
}
So here is the order of things.
// the constructor is run and the test method defined BUT NOT executed.
TestSupplierImpl test = new TestSupplierImpl(); // line 1
// Now you define model
test.model = new TestSupplierModel(3); // line 2
// Then you execute the predictate via get()
Boolean resultado = test.get(); // line 3
model and something aren't required until you issue the get() method. By that time they are already defined.

Converting Promise to different type even if result not yet available

I have the following activity:
#ActivityRegistrationOptions(defaultTaskScheduleToStartTimeoutSeconds = 300, defaultTaskStartToCloseTimeoutSeconds = 10)
#Activities(version="1.0")
public interface MyActivities {
B first(A a) throws Exception;
void second(C c) throws Exception;
}
And I have the following workflow:
public class MyWorkflowImpl implements MyWorkflow {
#Autowired
private MyActivitiesClient operations;
#Override
public void start(SomeType input) {
A a = new A(...);
Promise<B> b = operations.first(a);
Promise<C> c = ...;
/* Here, I would like to create c based on b */
operations.second(c);
}
}
Now b is not available until the first operation finishes, but the workflow continues even if b is not available.
Any idea?
Use #Asynchronous annotation of a method:
public void start(SomeType input) {
A a = new A(...);
Promise<B> b = operations.first(a);
Promise<C> c = ...;
operations.second(c);
}
#Asynchronous
private Promise<C> calculateC(Promise<B> b) {
Settable<C> result = new Settable<C>();
/* Here create c based on b */
result.set(b.get()....);
return result;
}
A method annotated as #Asynchronous is internally converted to a callback that is invoked when all its parameters of type Promise are ready. #Asynchronous implementation relies on AspecJ so make sure to follow setup instructions carefully to enable it.
Another option is to use Task:
#Override
public void start(SomeType input) {
A a = new A(...);
Promise<B> b = operations.first(a);
Promise<C> c = new Settable<C>();
new Task(b) {
protected void doExecute() {
/* Here c based on b */
c.set(b.get() ....);
}
}
operations.second(c);
}
Task doExecute method is invoked when all parameters of type Promise passed to Task constructor are ready.

How to mock methods/functions provided by Traits in Groovy

Here's an example:
trait Sender {
def send(String msg){
// do something
}
}
class Service implements Sender {
def myMethod1(){
send('Foo')
myMethod2()
}
def myMethod2(){
}
}
I am trying to test the Service class. However, I would like to stub/mock the calls to the methods provided by the trait (send)?
I have tried several different ways to stub/mock the method send, with no success:
// 1
Service.metaclass.send = { String s -> // do nothing }
// 2
def service = new MyService()
service.metaClass.send = { String s -> // do nothing }
// 3
StubFor serviceStub = new StubFor(Service.class)
serviceStub.demand.send { String s -> // do nothing }
//
trait MockedSender {
def send(String msg) { // do nothing }
}
def service = new Service() as MockedSender
These are just some of the things I tried. I even tried using Mock frameworks like Mockito. Unfortunately, nothing seems to work. Any suggestions???
Try using Spy from Spock framework!
Like this:
trait Sender {
def send(String msg){
println msg
}
}
class Service implements Sender {
def myMethod1(){
send('Foo')
myMethod2()
}
def myMethod2(){
println 'real implementation'
}
}
class UnitTest extends Specification {
def "Testing spy on real object"() {
given:
Service service = Spy(Service)
when:
service.myMethod1()
then: "service.send('Foo') should be called once and should print 'mocked' and 'real implementation' on console"
1 * service.send('Foo') >> { println 'mocked' }
}
}

How to code Writable Interface in groovy

hoping to use groovy to write a groovy.text.Template for Asciidoctor markup. So far :
//-----------------------------------
public class AsciidocTemplate implements groovy.text.Template
{
boolean includeHeaderFooter = true;
Asciidoctor asciidoctor = create();
org.asciidoctor.Options asciidoctorJOptions=["backend": "html","header_footer":includeHeaderFooter]
def payload="";
Map binding = [:]
public AsciidocTemplate()
{
} // end of constructor
public AsciidocTemplate(def payload)
{
this.payload = payload;
} // end of constructor
// use doctor to transform the template
public Writable process()
{
def output = asciidoctor.render(this.payload, asciidoctorJOptions);
Writer ou = output;
return ou;
} // end of make
Writable make()
{
return process(); //output as Writable;
} // end of make
// -----------------------------------
The render() returns a string, how do we convert that string into an object that implements the Writable interface, i just dont get it. Also can't see how to use/read/store the returned 'Writable' object either :-P
You can use the asWritable method on a Closure to get a Writable returned, ie:
Writable process()
{
def output = asciidoctor.render(this.payload, asciidoctorJOptions);
{ w -> w.println output }.asWritable()
}

Categories

Resources