In Retrofit 2, service methods representing http methods must return Call.
Call is a generic which must take the type representing the return object of the http method.
For example,
#GET("/members/{id}")
Call<Member> getMember(#Path("id") Long id);
For http methods such as delete, no content is returned. In cases like this, what parameter should be provided to Call?
Just set Void as the Type.
#DELETE("/members/{id}")
Call<Void> removeMember(#Path("id") Long id);
If you are using Kotlin/Retrofit/Rxjava/RxKotlin
#Headers(JwtKeyTokenWithValue)
#DELETE("/members/{id}")
fun removeMember(#Path("id") Long id): Completable
And can be subscribed this way
apiManager
.removeMember()
.subscribe(
{ Timber.i { "Member Removed!" } },
{ t -> Timber.e(t)})
Related
I've an interface like this:
public interface ICustomer extends IEnd<Customer> {
String getId();
ICustomer id(String id);
ICustomer email(String email);
ICustomer description(String description);
}
I need to mock any methods which returns an ICustomer regardless of parameters.
When these methods are called, the self called ICustomer have to be returned.
Any ideas?
To do this you need a custom Answer class:
public class CustomerAnswer implements Answer {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Class retType = invocation.getMethod().getReturnType();
if (ICustomer.class.isInstance(retType)) {
return invocation.getMock();
}
// provide default logic here -- override with "when()" calls.
return null;
}
}
Then create your mock, specifying the default behavior:
Foo mockCustomer = mock(ICustomer.class, new CustomerAnswer());
Add, when() statements for other methods that need to be stubbed.
But as I commented in the OP, be sure you actually want to mock this class before you go thru all the trouble. Only mock when it will make the test code simpler. If you have some simple implementation of the interface that is just a POJO with fluent API (no side-effects, no complicated dependencies or injections), there is probably no need to mock it. Instead use a real instance, because the real instance already returns the original object.
If you need to verify() on the ICustomer object, then use a #Spy of a real instance of a ICustomer.
I am creating a Groovy project and I would like to pass a method as a parameter is this possible?
I have 2 methods, which basically do the same thing but have a few small differences, each have different properties.
I would like to send through whether to use the 'buildPayLoad' function or
'buildSecondPayLoad' into my sendEmail function.
private Operation sendEmail(Order order) {
def payload = buildPayload(order, templateId)
}
private firstEmailPayLoad buildPayload(Order order, String templateId) {
new firstEmailPayLoad(
templateId,
config.fromAddress,
order.firstPayLoadProperty,
buildEmailDataFirstPayLoad(order)
).validate()
}
private secondEmailPayLoad buildSecondPayLoad(Order order, String templateId) {
new secondEmailPayLoad(
templateId,
config.fromAddress,
config.bccAddress,
config.otherProperty,
order.secondPayLoadProperty
buildEmailData(order)
).validate()
}
You can just do:
private Operation sendEmail(Order order, Closure builder) {
def payload = builder(order, templateId)
}
Then call it with:
sendEmail(order, this.&buildPayload)
Or
sendEmail(order, this.&buildSecondPayLoad)
BTW: You really should start class names with a capital letter, so instead of secondEmailPayLoad, you should call it SecondEmailPayLoad (and the same with firstEmailPayLoad)
If one pass a method as a funarg, how one can tell if passed function is a method, and get `this' object of a method is?
class A {
public function f():Void{
trace("f");
}
}
class B {
static function withFunarg(f:Void->Void):Void{
//HERE
}
public static function main(){
var a = new A();
withFunarg(a.f);
}
}
You cannot and there is no way to retrieve this. But it seems to me like an anti-pattern trying to do that. If you want the method and the container you can define a typedef:
typedef F = {
f : Void -> Void
}
Now you have the method and the container.
Haxe doesn't offer a cross-platform way to do that and it is generally not recomended.
But if you ultimately need this feature, you can use some platform-specific ways.
For example on js the following will work(at least on current haxe dev version):
static function getThis(f:Dynamic):Dynamic{
return (f.scope && f.method) ? f.scope : null;
}
It will return the object if the function is a method and a null otherwise. Result on calling on non-function is unspecified.
If you want to get the implicit `this' argument of a method, you have to make it explicit, like this
static function withMethodFunarg(o:{}, f:{}->Void):Void{
//HERE you have both object and function on this object
trace(o);
f(o);
}
public static function main(){
var a = new A();
withMethodFunarg(a,function(a){a.f()});
}
Which is, actually, pretty straight-forward: function is a function, no implicits, method caller is a method caller.
I have several ServiceStack request DTOs that implement an interface called IPageable. I have a validator that can validate the two properties that are on this interface. I think I'm going to end up having one validator per request type, but I'm trying to avoid having to duplicate that IPageable-related validation logic in all of them.
public class PageableValidator : AbstractValidator<IPageable>
{
public PageableValidator()
{
RuleFor(req => req.Page)
.GreaterThanOrEqualTo(1);
RuleFor(req => req.PageSize)
.GreaterThanOrEqualTo(1)
.When(req => req.Page > 1);
}
}
Some ideas I've had about this include:
It appears I can't just have container.RegisterValidators() apply
this to all request types that implement IPageable, but that was my
first thought.
can I specify multiple <Validator> attributes on all the request
definitions, so that both a request-specific validator runs, as well
as my IPageable validator?
can I specify at validator registration time that for all types
implementing IPageable, my IPageable validator should run?
can I write a base class for my request-specific validators that
gets the rules from my PageableValidator and includes / runs them?
I can make something sort of work by subclassing AbstractValidator<T> where T : IPageable , but I'd like to be able to do validation on more than one interface in more of an aspect-oriented way.
I don't know the answers to your questions but a few options came to mind to after reading your question.
I am not familiar with the <Validator> attribute, but in regards to question 2, you could create a Filter attribute that would run your paging validation. This allows you to use many attributes on your request and set their priority.
public class PageableValidator : Attribute, IHasRequestFilter
{
public void RequestFilter(IHttpRequest req, IHttpResponse res, object requestDto)
{
if (requestDto is IPageable)
{
var validator = new PageableValidator(); //could use IOC for this
validator.ValidateAndThrow(requestDto as IPageable);
}
}
public IHasRequestFilter Copy()
{
return (IHasRequestFilter)this.MemberwiseClone();
}
public int Priority { get { return -1; //setting to negative value to run it before any other filters} }
}
Another option would be creating an abstract class for Paging validation. This would require a subclass for every Request and requires a bit more code and some repetition*. Though, depending on how you want to handle your error messages you could move the code around.
public abstract class PagerValidatorBase<T> : AbstractValidator<T>
{
public bool ValidatePage(IPageable instance, int page)
{
if (page >= 1)
return true;
return false;
}
public bool ValidatePageSize(IPageable instance, int pageSize)
{
if (pageSize >= 1 && instance.Page > 1)
return true;
return false;
}
}
public class SomeRequestValidator : PagerValidatorBase<SomeRequest>
{
public SomeRequestValidator()
{
//validation rules for SomeRequest
RuleFor(req => req.Page).Must(ValidatePage);
RuleFor(req => req.PageSize).Must(ValidatePageSize);
}
}
IMO, the repetition makes the code more explicit (not a bad thing) and is okay since it isn't duplicating the logic.
I am creating a general general mock-client for testing HTTP-interactions. For this, I would like to be able to make a number of responses of the same method.
With a normal mock, this would not be a problem:
when(mock.execute(any(), any(), any())).thenReturn(firstResponse, otherResponses)
However, I am using a partial mock, where I simply want to mock method making the HTTP request, since there might not be access to a live end-point or the Internet in general for that matter in the context where the unit-tests are executed.
So I will be doing something like:
doReturn(response).when(spy).execute(hostCaptor.capture(), requestCaptor.capture(), contextCaptor.capture());
However, I would like to be able to support more than one response (not much of an "interaction"). But there are no doReturn-method, which takes a more than a single response at a time.
My first attempt on a solution was to do it iteratively:
Stubber stubber = null;
for (HttpResponse response : responses) {
if (stubber == null) {
stubber = doReturn(response);
} else {
stubber = stubber.doReturn(response);
}
}
stubber.when(spy).execute(hostCaptor.capture(), requestCaptor.capture(), contextCaptor.capture());
This does however fail to verify ("Unfinished stubbing detected") when running the test.
So - is there a way to achieve this with Mockito?
Thanks for reading.
You can write
doReturn( 1 ).doReturn( 2 ).doReturn( 3 ).when( myMock ).myMethod( any(), any(), any());
Edit:
If the values you want are in the array myArray, then you could also use
import static java.util.Arrays.asList;
import static org.mockito.Mockito.doAnswer;
import org.mockito.stubbing.answers.ReturnElementsOf
....
doAnswer( new ReturnsElementsOf( asList( myArray )))
.when( myMock ).myMethod( any(), any(), any());
The solution I found, was to use doAnswer to return the next response in the array.
Answer<HttpResponse> answer = new Answer<HttpResponse>() {
HttpResponse[] answers = responses;
int number = 0;
#Override
public HttpResponse answer(InvocationOnMock invocation) throws Throwable {
HttpResponse result = null;
if (number <= answers.length) {
result = answers[number];
number++;
} else {
throw new IllegalStateException("No more answers");
}
return result;
}
};
doAnswer(answer).when(spy).execute(hostCaptor.capture(), requestCaptor.capture(), contextCaptor.capture());