Expect the creation of a new object - ruby

I need to write an expectation that a new object will be created in a payment system. Code included from order.rb and order_spec.rb (Order class is here):
#order.rb
def confirm_order(method_of_payment)
if credit_card_but_products_out_stock?(method_of_payment)
raise "Cannot make credit card payment now, as some products are out of stock"
end
order_total
Payment.new(method_of_payment, self.total)
end
#order_spec.rb
it 'it creates a new payment object if method_of_payment is valid and order.total is > 0' do
order.add_product(product, 3)
order.confirm_order(:credit_card)
#Expect that a new payment object is created.
end
I want to understand how I can write the appropriate spec to test that the new Payment object is created. I found this article from Semaphore CI useful, but am not sure about a solution. I am pretty sure I should be creating a test double of some sort, and then maybe a method stub to allow(order).to receive(:confirm_order).and_return(#new_object??).

If you're unit testing the Order class, then you shouldn't be mocking or stubbing the Order class. You could set an expectation on the Payment class to return a mock that you can then further assert as the return value of confirm_order method.
let(:payment) { double :payment }
it "returns a payment" do
expect(Payment).to receive(:new).with(:credit_card).and_return(payment)
order.add_product(product, 3)
expect(order.confirm_order(:credit_card)).to eq(payment)
end
This way, you are mocking the dependencies of your Order class, without altering the Order class, which is much safer as mocking method on Order could easily create false-positive test results.

Related

How to achieve update "batching" in factorybot for traits

Say you have a Factory in FactoryBot, and say that factory has several traits for associations, and that each trait will need to update the model being created by the factory. So, your main model is MainModel, and you have associations to A, B, C, D, etc...
FactoryBot.define do
factory :main_model
trait :with_a do
after(:create) do |main_model|
# Both sides refer to each other, so this must be done in after(:create).
main_model.update(a_id: create(:a, main_model_id: main_model.id).id)
end
end
trait :with_b do
after(:create) do |main_model|
# Both sides refer to each other, so this must be done in after(:create).
main_model.update(b_id: create(:b, main_model_id: main_model.id).id)
end
end
# More traits omitted...
end
Side note: We're not using ActiveRecord, so we cannot use the associations features built into FactoryBot. Associations must be explicitly registered using a call to update on both sides of the association. Even if I could, I'm not sure it would have any effect?
Now, if client code does the following:
create(:main_model, :with_a, :with_b, :with_c, :with_d)
This is going to result in the following writes to the db:
Create the main record
Create the A record that points to the main.
Update the main record to point to the new A.
Create the B record that points to the main.
Update the main record to point to the new B.
Create the C record that points to the main.
Update the main record to point to the new C.
Create the D record that points to the main.
Update the main record to point to the new D.
Of the above, Numbers 3, 5, 7, and 9 could all be done at the same time, at the very end, if I could simply build up a list of updates that are needed and find a "hook" that would allow me to do one more update after the final trait was applied, and factory bot was ready to return the final result to me. I cannot figure out a way to do that, but the ability to do this would save thousands (probably tens of thousands) of DB writes across my spec suite.
Anyone have any ideas?
You could define a transient variable (I used associations, but call it whatever) - and use this to store all of the associated record IDs for a single record update in an after(:create) block.
Something like this:
FactoryBot.define do
factory :main_model do
transient do
associations { {} }
end
trait :with_a do
associations { super.merge(a_id: create(:a, main_model_id: id).id) }
end
trait :with_a do
associations { super.merge(b_id: create(:b, main_model_id: id).id) }
end
after(:create) do |main_model|
main_model.update(associations)
end
end
end
Usage of the factory remains unchanged - e.g.
create(:main_model, :with_a, :with_b)
...So you shouldn't need to update any of the spec code.

Use the result of checked method inside conditional statement

I'm trying to implement and Authorization module, because currently the authorization logic for a certain resource is separated on two or three different places and even though I'm not sure this is the best approach, at least I think it will provide some encapsulation.
Since I'm checking for several different things
Does the user have the right role
Is the resources in the right state to process the required action
Do the user has the right to perform the required action on this particular resource
So as you can see, there are several checks, I'm not pretending to be completely correct here, but this is pretty close to the real case, so I've decided to use something like a Result Object even though it's actually not an object but a struct and I'm not using Gem but pretty simple custom implementation.
So part of my Authorization module is this:
module Authorization
Result = Struct.new(:successfull?, :error)
extend self
def read(user, resource, message: 'Permission denied')
can_read =
[
condition1,
condition2,
condition3
]
return Result.new(can_read.any?, can_read.any? ? nil : message))
end
However within this Authorization module I have a lot of methods and some of them check read internally like so:
def assign(user, resource, message: 'Permission denied')
return read(user, resource) unless read(user, resource).successfull?
Result.new(true, nil)
end
So my main question is how to avoid this double call to read(user, resource). I guess one option would be to just call it before the check like:
result = read(user, resource)
return result unless result.successfull?
However I'm pretty new to Ruby and I suspect that maybe there is more ruby-like way to do this. Just to inline it somehow by assigning the result from read inside the condition check...However this is just wild guess.
And one more question, that came up while I was writing this. Currently if I want to send nil for message when the authorization passes I'm doing this:
return Result.new(can_read.any?, can_read.any? ? nil : message))
Because message unless can_read.any? is throwing and error even though I thought it would default to nil. So again, is there some more ruby-like way to do this?
First part can be written with Object#yield_self:
def assign(user, resource, message: 'Permission denied')
read(user, resource).yield_self do |res|
res.successful? ? Result.new(true, nil) : res
end
end
successfull? -> successful? for English reasons. I am not convinced this is more readable than using a local variable though. Alternatively:
(res = read(user, resource)).successful? ? Result.new(true, nil) : res
As for your second question, you'll need more parentheses
Result.new(can_read.any?, (message if can_read.none?))
the return is not needed.
I would also advise you to slow down with all the unlesses, try to swap your conditions to if whenever possible -- I find it quite useful to make Result a class and define a failed? method for it. Actually, I'd consider this:
class Result
def initialize(error)
#error = error
end
def successful?
#error.nil?
end
def failed?
!successful?
end
end
That depends on how complicated your Result gets, but for the use case shown, it would be a little cleaner imho.

Trying to understand what a Method is, how can it be 'part of a class'?

I've done some work with functions in Javascript, and thought that a Method was the Ruby name for the same. I recently did a technical interview and the interviewer was trying to help me debug by explaining how Methods were part of a class, and that it's an OOP thing.
I can't spot a functional difference between a Method and an equivalent Function, so I don't see what classes have to do with it.
Can you explain the whole 'Methods are part of a class' thing and why it matters? How can a Method be part of a class? Class as in an integer or a string?
The interviewer believed it would help, but it seems like a tiny technicality more than something useful.
Can you explain the whole 'Methods are part of a class' thing and why it matters? How can a Method be part of a class? Class as in an integer or a string?
Let's say you have two classes, Apple and Cake. Let's assume that when you sell an apple, it has a tax rate of 10%, and cake 20%. By splitting the methods into individual classes, we can define a different method for 'price_with_tax' to each class:
class Apple < ApplicationRecord
def price_with_tax
self.price * 1.1
end
end
class Cake < ApplicationRecord
def price_with_tax
self.price * 1.2
end
end
In javascript we wouldn't be able to do this, and would need to have 2 methods, 'add 10% tax' and 'add 20% tax'. By structuring the methods as we have, we're able to do:
apple = Apple.find(1)
cake = Cake.find(1)
cake.price_with_tax
apple.price_with_tax
Methods are generally something that a class can do,
class MailClient(for example) might have methods such as sendMail, getMail, forwardMail, etc. In OOP, methods should for the most part be something that a class can do.
MailClient.getMail();
The above code can be conceptualized as telling the class to invoke its getMail() behavior.
You may think of this in real-life terms such as:
Dog.bark();
Objects have behavior and attributes, the behaviors are the methods.
In OOP:
Class is like a blueprint/template. It has properties, methods etc. An object can be created with it. So an object can call method in class.
Usually a method is created to perform an operation.
Example:
// a demo class
public class Animal{
// a method
public void sound(){
// do something...
}
// main class, we create an object and call sound() method
public static void main(String[] args){
Animal dog = new Animal(); // create an object so that we can use the method
dog.sound(); // method call
}
}

Mocking RestTemplate call with Mockito

I have the following code that is inside of a method that I am testing. I need to mock this restTemplate call to get predictable result.
GitHubEmail[] gitHubEmails = restTemplate
.getForObject(userEmailsUrl, GitHubEmail[].class, oAuthToken);
In the test method, I do this:
RestTemplate mockRestTemplate = Mockito.mock(RestTemplate.class);
GitHubEmail fakeGitHubEmail = new GitHubEmail("testemail#email.com",
false, false, GitHubEmailVisibility.PRIVATE);
GitHubEmail[] fakeEmails = {fakeGitHubEmail};
Mockito.when(mockRestTemplate.getForObject(
Mockito.eq(userUrl),
Mockito.eq(GitHubEmail[].class),
Mockito.eq(testOAuthToken)))
.thenReturn(fakeEmails);
gitHubService.setRestTemplate(mockRestTemplate);
User user = gitHubService.getUser(testOAuthToken);
Things aren't working as I expect them to... When I examine gitHubEmails variable in my method I am testing, it's null.
Why isn't this working?
The current code as it is right now does not contain any mistakes. However, there are two things we don't see from the given code:
We don't see that testOAuthToken is properly passed to the oAuthToken variable within the githubService.
We don't see that the userUrl is passed to the userEmailsUrl within githubService.
You should make sure that all properties match the one you expect them to be, otherwise the mocking doesn't work. Given that you named one property userUrl and the other one userEmailsUrl, it's likely that the error is there.
Usually, when I encounter these error-prone mocking situations, I use "any matchers" (any(), anyString(), ...) when mocking and then after the call and the assertions, I use Mockito.verify() to check if the parameters match:
Mockito.when(mockRestTemplate.getForObject(
Mockito.anyString(), // Use anyString()
Mockito.eq(GitHubEmail[].class),
Mockito.anyString())) // Use anyString()
.thenReturn(fakeEmails);
// Call + Assertions ...
Mockito.verify(mockRestTemplate).getForObject(
Mockito.eq(userUrl), // Use eq()
Mockito.eq(GitHubEmail[].class),
Mockito.eq(testOAuthToken)); // Use eq()
The reason for this is that the verify() output gives a lot more feedback. Rather than just failing, it will tell why it failed when:
The mocked method was called with different arguments, and which arguments
The mocked object had different methods being invoked

Is it ok for a Django mixin to inherit another mixin?

I'm pretty sure the answer to this question is obviously "NO", since Django mixins are supposed to
inherit "object"s, but I can't find an alternative solution to my problem :(
To make the question as simple as possible,,,
views.py
class JSONResponseMixin(object):
def render_to_response(self, context):
"Returns a JSON response containing 'context' as payload"
return self.get_json_response(self.convert_context_to_json(context))
def get_json_response(self, content, **httpresponse_kwargs):
"Construct an `HttpResponse` object."
return http.HttpResponse(content,
content_type='application/json',
**httpresponse_kwargs)
def convert_context_to_json(self, context):
"Convert the context dictionary into a JSON object"
# Note: This is *EXTREMELY* naive; in reality, you'll need
# to do much more complex handling to ensure that arbitrary
# objects -- such as Django model instances or querysets
# -- can be serialized as JSON.
return json.dumps(context)
class HandlingAJAXPostMixin(JSONResponseMixin):
def post(self, request, *args, **kwargs):
.....
data = {'somedata': somedata}
return JSONResponseMixin.render_json_response(data)
class UserDetailView(HandlingAJAXPostMixin, DetailView):
model = MyUser
.....
So the problem I have is that, for multiple Views, I want to respond to their "post" request with the same
JSON Response. That is why I defined the HandlingAJAXPostMixin so that I could reuse it for
other Views. Since the HandlingAJAXPostMixin returns a JSON response,
it requires a render_json_response method, which is defined in the JSONResponseMixin.
This is the reason why I am making my HandlingAJAXPostMixin inherit the JSONResponseMixin, but this obviously seems wrong :(..
Any suggestions..?
Thanks!!!
It's perfectly valid for a mixin to inherit from another mixin - in fact, this is how most of Django's more advanced mixins are made.
However, the idea of mixins is that they are reusable parts that, together with other classes, build a complete, usable class. Right now, your JSONResponseMixin might as well be a separate class that you don't inherit from, or the methods might just be module-wide methods. It definitely works, there's nothing wrong with it, but that's not the idea of a mixin.
If you look at Django's BaseDetailView, you see the following get() method:
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
get_object() and get_context_data() are defined in the subclasses of BaseDetailView, but render_to_response() isn't. It's okay for mixins to rely on methods that it's superclasses don't define, this allows different classes that inherit from BaseDetailView to supply their own implementation of render_to_response(). Right now, in Django, there's only one subclass, though.
However, logic is delegated as much as possible to those small, reusable methods that the mixins supply. That's what you want to aim for. If/else logic is avoided as much as possible - the most advanced logic in Django's default views is:
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
That's why very similar views, like CreateView and UpdateView are in fact two separate views, while they could easily be a single view with some additional if/else logic. The only difference is that CreateView does self.object = None, while UpdateView does self.object = self.get_object().
Right now you are using a DetailView that defines a get() method that returns the result of self.render_to_response(). However, you override render_to_response() to return a JSON response instead of a template-based HTML response. You're using a mixin that you don't what to use (SingleObjectTemplateResponseMixin) and then override it's behavior to do something that you don't want to do either, just to get the view doing what you want it to do. A better idea would be to write an alternative for DetailView who's only job is to supply a JSON response based on a single object. To do this, I would create a SingleObjectJSONResponseMixin, similar to the SingleObjectTemplateResponseMixin, and create a class JSONDetailView that combines all needed mixins into a single object:
class SingleObjectJSONResponseMixin(object):
def to_json(context):
return json.dumps(context)
def render_to_response(context, **httpresponse_kwargs):
return HttpResponse(self.to_json(context),
context_type='application/json',
**httpresponse_kwargs)
class BaseJSONDetailView(SingleObjectMixin, View):
# if you want to do the same for get, inherit just from BaseDetailView
def post(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return render_to_response(context)
class JSONDetailView(SingleObjectJSONResponseMixin, BaseJSONDetailView):
"""
Return JSON detail data of a single object.
"""
Notice that this is almost exactly the same as the BaseDetailView and the SingleObjectTemplateResponseMixin provided by Django. The difference is that you define a post() method and that the rendering is much more simple with just a conversion to JSON of the context data, not a complete template rendering. However, logic is deliberately kept simple as much as possible, and methods that don't depend on each other are separated as much as possible. This way, SingleObjectJSONResponseMixin can e.g. be mixed with BaseUpdateView to easily create an AJAX/JSON-based UpdateView. Subclasses can easily override the different parts of the mixins, like overriding to_json() to supply a certain data structure. Rendering logic is where it belongs (in render_to_response()).
Now all you need to do to create a specific JSONDetailView is to subclass and define which model to use:
class UserJSONDetailView(JSONDetailView):
model = MyUser

Resources