Making the body of a function use a mock of an object - ruby

I have the following method in a controller:
def webhook
data_json = JSON.parse(request.body.read) # it comes from the test, it's OK
event = Stripe::Event.retrieve(data_json[:id]) # it's not OK, it's a real request to Stripe
stripe_cust_id = event.data.object.customer
user = User.where(stripe_customer_id: stripe_cust_id)
#.....
In a spec file I create a mock for event and then make a post request to webhook in a test. I'm not allowed to change the body or signature of webhook because I'm testing it. So how do I make it use the mock I create?
describe '#webhook' do
it 'something' do
user = FactoryGirl.create(:user)
event = StripeMock.mock_webhook_event('invoice.payment_succeeded')
post(:webhook, event.to_json)
#error because webhook makes a real request to Stripe

mock(Stripe::Event).retrieve(any) do
event
end
That should return event from any call to retrieve on Stripe::Event. Works with rr.

If your concern is only about external requests, you can try something like Vcr or WebMock to mock the responce.

Related

one LAMBDA function work with few methods

I have an API that has different methods - (GET, POST, DELETE) Is there a way to make one LAMBDA function work with all of these methods or does each method have its own LAMBDA function?
I mean I have parts in the code that each part is supposed to work in calling a different method.
and what if i have a few resources?
client = boto3.resource('dynamodb')
table = client.Table('papi.table')
def lambda_handler(event, context):
//for GET METHOD
tab= table.scan()
item = tab['Items']
for id in item:
print(id)
// for POST
response = table.put_item(
Item={
'id':"1"
}
)
return response
and so..
You can get the httpMethod parameter from the event, see Documentation for the API gateway response to the Lambda.

list_comments Ruby implementation with YouTube video_id

Having trouble implementing the list_comments method in the following code example (n.b. the API is initialised successfully):
# initialize API
service = Google::Apis::YoutubeV3::YouTubeService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize
response = service.list_comments('snippet, replies')
Currently the method returns the following error:
missingRequiredParameter: No filter selected. Expected one of: id, idParam, parentId (Google::Apis::ClientError)
I have successfully tested the API call here:
https://developers.google.com/youtube/v3/docs/comments/list
What I'm struggling with is when I test the API call I can pass a videoId to identify a resource, however the method implementation does not allow for this. Could anyone shed some light on how to pass a videoId to the method call?
Found the solution! The method that allows you to specify video_id (or channel_id) to select a specific resource is: list_comment_threads from the Google::Apis::YoutubeV3::YouTubeService module.
response = service.list_comment_threads('snippet', video_id: 'hy1v891n3kA').to_json

How can I use SwaggerValidator(com.atlassian.oai.validator) to validate Lagom API Response?

Well, I am stuck in this scenario that I want to use Swagger API to validate response of my Lagom Service API.
Here is some sample code:
#Test
public void shouldPayloadFromFileConformToSchema() throws Exception {
// first test the plain json is valid with schema
SwaggerRequestResponseValidator validator = SwaggerRequestResponseValidator
.createFor("my-service-schema.yaml").build();
final Request validRequest = SimpleRequest.Builder.get("/myService/AL20170730/11111555556161/191919")
.withHeader("api-key", "TESTKEY")
.build();
Response validResponse = SimpleResponse.Builder.ok()
.withBody(ValidatorTestUtil.loadResponse("my_service_sample_response_2017_03_16")).build();
ValidationReport reportForText = validator.validate(validRequest, validResponse);
logger.info(
"shouldPayloadFromFileConformToSchema() ################# VALIDATION PAYLOAD REPORT ##################");
reportForText.getMessages().forEach((m) -> {
logger.info("{}", m);
});
assertFalse(reportForText.hasErrors());
logger.info(
"shouldPayloadFromFileConformToSchema() ################# VALIDATION PAYLOAD REPORT END ##################");
logger.info(validRequest.getHeaders().toString());
SwaggerModule swagger = new SwaggerModule();
}
When This code runs It seems that it goes into the service(as it prints some logs of the service.) but not invokes the method which will the database with the given values.
I need to do something here that it invokes the method of the service and validates the response on the basis of this swagger spec.
I saw this link but didn't get the solution How to validate API in tests with Swagger?
If you're looking to validate an actual interaction against your running service I'd recommend using the RestAssured module (https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-restassured/)
This will let you execute a request against your running service and then validate that the request/response interaction matches your swagger specification.
There's an example of its use in the examples module - https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-examples/src/test/java/com/atlassian/oai/validator/examples/restassured/SwaggerValidationFilterTestExample.java (note that the example there uses WireMock to stub out a real service, but you would replace that with your actual running service).

Stubbing API calls in controller with rspec

I am just a little confused at why I can't stub a local variable in my controller spec.
Here is my controller:
Class UsersController < ApplicationController
...
def get_company
resp = Net::HTTP.get("http://get_company_from_user_id.com/#{params[:id]}.json")
#resp = JSON.parse(resp.body)
...
My spec looks like:
class ResponseHelper
def initialize(body)
#body = body
end
end
describe "Get company" do
it "returns successful response" do
stub_resp_body = '{"company": "example"}'
stub_resp = ResponseHelper.new(stub_resp_body)
controller.stub!(:resp).and_return(stub_resp)
get :get_company, {:id => #test_user.id}
expect(response.status).to eq(200)
end
end
I still get an error saying that:
Errno::ECONNREFUSED:
Connection refused - connect(2)
What am I doing wrong? If I am stubbing the resp variable why is it still trying to do the HTTP request and how would I stub the resp variable in this case?
You just cannot stub a local variable, you can only stub methods. In your case you can stub the Net::HTTP.get method:
Net::HTTP.stub(:get).and_return(stub_resp)
There is no such thing as 'stubbing a local variable'. The only thing that can be stubbed are method calls.
You would need the stub the Net::HTTP.get call to return something that looks like a Net::HTTPResponse that the rest of your code can work with.
I quite often like to tidy this up by having a client class for each api that knows how to generate the url from the arguments (in this case the id) and how to parse the response. This keeps those details out of the controller and also makes testing easy, since now you can provide a mock client object
You cannot stub a local variable. Just a method. As there were answers above you may want to stub Net::HTTP.get call. However, if you don't want to have you code rely upon a particular HTTP client library you can extract the http request into another method of a controller and stub this method
Class UsersController < ApplicationController
...
def get_company
resp = make_request(params[:id)
#resp = JSON.parse(resp.body)
end
protected
def make_request(id)
Net::HTTP.get('http://get_company_from_user_id.com/#{id}.json')
end
controller.
should_receive(:make_request).
with(#test_user.id).
and_return(stub_resp)

How would I write test for following controller

I am new to rspec and was wondering how could I write functional test for following two action of controller
class FeedbackFormsController < ApplicationController
before_filter :authenticate_user!
def new
#feedback_form = FeedbackForm.new
session[:return_to] = request.referer
end
def create
feedback_form = FeedbackForm.new(params[:feedback_form])
FeedbackMailer.new(feedback_form).deliver
flash[:notice] = "Your feedback was submitted successfully."
redirect_to session[:return_to]
end
end
I think it's probably a better learning experience for you to do it yourself, but I'll get you started with some pseudo-ish code. I will be purposely lax with my syntax.
require spec-helper
describe FeedbackFormsController
before each
controller should receive :authenticate_user! and return true
describe new
it should assign a new feedback form
get new
assigns feedback_form should be a new Feedbackform
it should call for the referer
request should receive referer
get new
it should set session value
request stub referer and return nonsense
expect
get new
to change session return_to to nonsense
describe create
it should create a new Feebackform
Feebackform should receive new with nonsense
post create nonsense
it should create a new Feebackmailer
mock = mock_model Feedbackform
Feedbackform stub new and return mock
Feedbackmailer should receive new with mock
post create nonsense
it should deliver a message
mock = mock_model FeedbackMailer
Feedbackform stub new
FeedbackMailer stub new and return mock
mock should receive deliver
post create nonsense
it should redirect
Feedbackform stub new
Feedbackmailer stub new
post create nonsense
response should redirect to session[return to]
Hopefully that should get you started.

Resources