I'm using the PowerMockito and Mockito libraries. In mocking a method I need to declare a return value only if the method input, which is of the type JsonObject, satisfies some conditions. For example, for all inputs that the value for the key query equals to queryValue, return the declared value.
I ended in the following code where I can check the input in the then method which is good but the problem is I think for JsonObjects where the condition does not satisfy, it will return a null value as I must return a value for the then method.
final String queryValue = "some values";
PowerMockito.when(instance.myMethod(Mockito.any(JsonObject.class)))
.then(ans -> {
JsonObject input = ans.getArgument(0);
if (queryValue.equals(graphQlQuery.getString("query")))
return resultValue;
else
return null;
});
So I was wondering is there any way to specify such a condition on inputs when a method is being called?
Thanks
You need to use a different argument matcher than any. Mockito Documentation has examples that show how to match different arguments.
In your example, you don't need something complicated:
.when(instance.myMethod(ArgumentMatchers.argThat(
(JsonObject input) -> queryValue.equals(input.getString("query"))
)))
.thenReturn(resultValue)
the problem is I think for JsonObjects where the condition does not satisfy, it will return a null value as I must return a value for the then method.
Just to avoid any misunderstanding: If you use the code above, the mock still returns a default value (null) for the calls that are not matched by any stubs.
What is different with this code is that you can add other stubs with different matchers, that handle different cases (when the argument is not "query"). In your original code, you had to handle all calls in the same place.
Related
I've got a generic function that needs to create a Tuple to call a function whose arguments I don't know the types of.
Something like this (except array in this example is created by some external code, so I can't just apply the function directly):
Result apply<Result, Where>(
Anything[] array,
Callable<Result, Where> fun)
given Where satisfies Anything[] => nothing;
Is there a type-safe way to implement this method and get the function to be called with the given arguments?
This cannot be done completely type-safely... but assuming that the array indeed contains elements of the correct types as they should appear in a Tuple of type Where, the following function will do the trick:
Tuple<Anything, Anything, Anything> typedTuple({Anything+} array) {
if (exists second = array.rest.first) {
return Tuple(array.first, typedTuple({ second }.chain(array.rest.rest)));
}
else {
return Tuple(array.first, []);
}
}
And apply gets implemented as:
Result apply<Result, Where>(
[Anything+] array,
Callable<Result, Where> fun)
given Where satisfies Anything[] {
value tuple = typedTuple(array);
assert(is Where tuple);
return fun(*tuple);
}
There's nothing relating the type of array to the parameters of fun, so that signature can't possibly be implemented in a type-safe way. You're not constraining the type of array at all; it could contain anything. How in principle would a type-safe implementation handle the case where fun expects [String, Integer] but array is [Boolean+]?
I am trying to use an instance variable as a parameter value in a method, but it is giving me an error. "Parameter initializer is unknown or is not a compile-time constant"
I want to use a non-constant instance variable though, and I assume there has to be some way around this besides calling this method from another method. Here is the code I'm referring to:
public function attack(target:Fighter=this.target):void {
}
What about:
public function attack(target:Fighter):void
{
if(target == null)
target = this.target;
}
and to be honest maybe it's easier to name one of variables _target to avoid confusion. You can use target = _target; instead of this..
You cannot set an optional parameter that way. You can set optional parameters to a default value but not a reference. In this case if you want to keep it optional you could do something like this (or what #George Profenza suggested):
public function attack(target:Fighter=null):void {
target = target ? target : this.target;
}
I see that you marked a correct answer already, but I'll explain that since you are defaulting any null parameters to this.target you would benefit from using this solution so you don't have to pass null each time you call attack() i.e. - you can do attack() instead of attack(null).
I'm trying to parse some JSON in Grails using the grails.converters.JSON library. I have a field which will contain either a string, or a null value. When I parse the JSON and get the field, the null values come back as a JSONObject.NULL type. This is not good when checking != null as JSONObject.NULL is evaluated as non-null (not good for null checks)
def obj = JSON.parse('{"date1":null,"date2":"2011-06-26T05:00:00Z"}')
def date1 = obj.date1
if (date1)
parse(date1) // parse error occurs here because date1 evaluates true in the if because it is JSONObject.NULL
Is there an easy way to get the parse to parse a real null value so that I don't have to check if the object is a JSONObject.NULL.
I tried the suggestion here to use .toString(), but it ended up returning the string value 'null' instead of actual null for a JSONObject.NULL value.
You may find this more useful and natural
JSONObject.NULL.equals(jsonObj.get("key_name"))
Have a look at: http://grails.1312388.n4.nabble.com/The-groovy-truth-of-JSONObject-Null-td3661040.html
Ian Roberts mentions a nice trick to make a null check possible:
JSONObject.NULL.metaClass.asBoolean = {-> false}
I think I found a better solution, which consists in overriding the toString() method implementation of the JSONObject.NULL inner class by copying the JSONObject.java file into your Grails src/java project and then changing the implementation to this:
/**
* Get the "" string value.
* #return An empty String "".
*/
#Override
public String toString() {
return "";
}
Once you restart with this new class in your classpath, the classloader will use your JSONObject class instead of the one packaged in the Grails dependencies.
Make sure you keep it in the same package as the original.
For more details you can go here: https://github.com/grails/grails-core/issues/9129
Hope it helps :-)
I am not sure if I am missing something here. I would like to compare two classes that uses the same interface. Is this possible? I understand that the is operator compares classes, but is there any similar function when you use interfaces?
// works
var effect1 : CrazyEffect = new CrazyEffect();
var effect2 : SaneEffect = new SaneEffect();
trace(effect1 is effect2) // false
// does not work
var effect1 : ISoundEffect = new CrazyEffect();
var effect2 : ISoundEffect = new SaneEffect();
trace(effect1 is effect2)
1067: Implicit coercion of a value of type ISoundEffect to an unrelated type Class.
Note the differences between concepts of a class and of an object. The former is a data type whereas the latter is a runtime instance of it, a variable. is operator can not compare one variable to another.
According to language reference
is Operator
Evaluates whether an object is compatible with a specific data type,
class, or interface. Use the is operator instead of the instanceof
operator for type comparisons. You can also use the is operator to
check whether an object implements an interface.
In other words, compiler expects the first operand to be a variable whereas the second operand should be a type identifier.
var sample:String = "Object is an instance of a class.";
^^^ ^^^
variable type identifier
However effect2 is not a type identifier but a variable. Hence the error message.
Unfortunately there is no generic operator to test for interface commonality. The only alternative is:
trace((s is ISoundEffect) && (t is ISoundEffect));
Update
Checking whether objects are instances of a same class can be done by comparing class names:
if (getQualifiedClassName(effect1) == getQualifiedClassName(effect2)) {
// true
}
For in depth discussion see Get the class used to create an object instance in AS3
Even though it will work with getQualifiedClassName, there's a better method to check whether two objects are instances of the same class:
a['constructor'] === b['constructor']
getQualifiedClassName is very slow and CPU intensive. Since the above code just compares property values it is lightning fast. And yes, constructor IS a property of every object, however FB will complain if you try to access it using dot-notation, that's why I use dynamic property access.
Consider the following test:
[Test]
public void Create_ServiceWithDynamicDependency_Created()
{
// arrange
IWindsorContainer container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IServiceFactory>().AsFactory());
container.Register(Component.For<ServiceWithDynamicDependency>().LifeStyle.Transient);
container.Register(Component.For<SomethingStatic>().LifeStyle.Transient);
var factory = container.Resolve<IServiceFactory>();
// act
ServiceWithDynamicDependency serviceWithDynamicDependency = factory.Create(null);
// assert
Assert.That(serviceWithDynamicDependency, Is.Not.Null);
}
This fails with the following exception: Could not resolve non-optional dependency for 'Testing.Windsor.Factory.ServiceWithDynamicDependency' (Testing.Windsor.Factory.ServiceWithDynamicDependency). Parameter 'somethingDynamic' type 'System.String'
If I replace the assert part with this:
ServiceWithDynamicDependency serviceWithDynamicDependency = factory.Create("foo");
The component is resolved as expected. Does anyone know of a workaround for this or do I have to hand-roll factories which accepts null arguments?
Although you didn't specify it I'm assuming your component has one constructor that looks like this:
public ServiceWithDynamicDependency(string somethingDynamic) {}
The behavior you're observing is not a bug - this is by design, and here's why.
If a value is required an actual value has to be provided, and null is not considered to be a correct value. Otherwise Windsor would just be passing null in for every constructor instead of bothering to find actual dependencies for that.
null is a special value in .NET and it means "no value". So even though you explicitly provide null as an argument Windsor will ignore it.
To solve this, instead of working around be explicit that the value is optional and provide a second constructor that does not include it.
Windsor is smart enough to pick the right constructor and if the value is not provided (or null as in your case) it will pick the no-argument constructor, and when the value is there (is not null) it will pick the one with the value.