Laravel mocking Model / QueryBuilder - unit-testing

I've been playing around with unit tests for a while but I've reached a point that I'm not sure how I can achieve what I want.
I've got a test that involves a JsonResource, and within this JsonResouce I have this sample.
'id' => $this->id,
'name' => $this->name,
'state' => $this->state->name,
'users' => UsersResource::collection($this->users()->limit($userLimit)->get()),
'clients' => ClientsResource::collection($this->clients()->limit($clientLimit)->get()),
My test involves calling this JsonResource, which is related to a model of Group, that contains users and clients alongisde some other attributes.
To mock the operation that is being done before calling this JsonResource, I've used a Mock on the repository that wraps my Group class, saying it should return an instance of Group:class. It then comes the time that the jsonresource is called with this Group instance, and I need to mock these attributes, but since clients() and users() are functions, I need to mock those since there is no database access. Here comes Mockery::mock(Group::Class)
$this->groupMock = Mockery::mock(Group::class);
$this->groupMock->shouldReceive('getAttribute')->with('id')->once()->andReturn(1);
$this->groupMock->shouldReceive('getAttribute')->with('state')->once()->(new GroupState(['name' => 'some group name']));
$this->groupMock->shouldReceive('getAttribute')->with('name')->once()->andReturn('something');
I'm wondering how I can make these lines below work. As far as I can tell, it doesn't recognise the order of the method calls or "concatenating" order. Is it achievable? How could I make this work?
$this->groupMock->shouldReceive('clients')->andReturn($this->groupMock)
->shouldReceive('limit')->with(6)->andReturn($this->groupMock)
->shouldReceive('get')->andReturn(collect(factory(User::class, 2)->make()));
$this->groupMock->shouldReceive('users')->andReturn($this->groupMock)
->shouldReceive('limit')->with(8)->andReturn($this->groupMock)
->shouldReceive('get')->andReturn(collect(factory(User::class, 6)->make()))

Related

In Rails4, using Trailblazer, how do I access the current_user

We are building a Rails4 app using Trailblazer. I have never worked with Trailblazer before and I am confused about how to do things.
We are building an auction site. I was previously using a traditional controller, and this route endpoint was working fine:
def bill
#profile = Profile.find_by user_id: current_user_id
#current_order = Order.order(created_at: :desc).find_by(user_id: current_user_id)
#batch = #current_order.batch
if #batch.nil?
puts "There was no batch linked to the current order of #{#current_order.id}"
flash[:error] = "We are sorry, but we could not determine which batch your order belongs to."
else
#price_shown_to_customer = #batch.price + ENV["FUELBID_FEE_PER_GALLON"].to_f
#amount = #current_order.quantity * #price_shown_to_customer
end
But now I'm suppose to create this as a Trailblazer api, using a Representer class.
So in routes.rb I added something for "charges":
namespace :api do
get '/price' => 'info#info'
post '/order' => 'orders#create'
get '/charges' => 'charges#bill'
end
I created this Api but copying-and-pasting another:
module Api
class ChargesController < ApiApplicationController
respond_to :json
def bill
respond_with OpenStruct.new.extend(ChargesRepresenter)
end
end
end
I tested the above with a simple Representer and it all worked fine, so everything is good up to this point. If I return simple data from the Representer, then I can see it fine here:
http://localhost:3000/api/charges.json
But I need to get the current_user. How is this done? Right now, this does not work:
module ChargesRepresenter
include Roar::JSON
collection :price_shown_to_customer
def price_shown_to_customer
current_order = Order.order(created_at: :desc).find_by(user_id: current_user_id)
puts "current_order"
puts current_order.id
batch = current_order.batch
batch.price + ENV["FUELBID_FEE_PER_GALLON"].to_f
end
end
current_user_id exists in my traditional controllers because we set up Devise and so my traditional controllers inherit it:
class ChargesController < SecuredController
But is there any way to get it in a Trailblazer Representer?
Hope this answer is not too late.
If you can switch to Decorator pattern instead of a Module.
Representer really doesn't need to know and doesn't care if it is called from controller or console or test. All it needs is a hash to build your json object from. So you can just pass another attribute called current_user_id to your Representer and then use it inside r presenter like you do.
FYI:
If you need a more immediate response you can also copy your question to https://gitter.im/trailblazer/chat . There are usually several people hanging out there. But it's also good to post a question here for posterity.

Outputting data with NanoStoreInMotion

I have successfully been able to create a user using NanoStoreInMotion. I can query on it and see the object. What I am having an issue with is outputting data. For example:
User model:
class User < NanoStore::Model
:first_name => "Jason"
:last_name => "Beam"
user = User.find(:first_name => "Jason")
#This returns the object [#<User:0xab96ab0>]
end
With ruby, normally to call on a specific field I would just do user.first_name. This throws an error, "undefined method 'first_name' for [#]:Array (NoMethodError)
If I remember correctly find returns an Array so you need to do something like user[0].first_name
Based on my experience I would advise against NanoStoreInMotion. I wouldn't exclude my own inability to use it correctly, but for me it was unreasonably slow (storing thousands of relatively complex objects) and throwing a lot of cryptic errors.
So I moved to MotionModel and I am very happy with it.

What assertions/tests are needed in a basic "Save/Submit" model test case?

Can anyone help me with what assertions are required in a basic save method test case in CakePHP 2.0?
I have Product, User and News model, I am looking to write a test case for the submit method in the News model and there are so many ways/things to include I was just wondering what is actually needed and what isn't. I have basic fixtures setup for all models.
The method I'm testing will effectively be this:
class News extends AppModel {
public submit($productId, $userId, $newsData) {
// Logic which checks for user and products existence, saves and returns submitted row
}
}
Test Case
public function testSubmit() {
// Save News
$newsData = array(
'News' => array(
'title' => 'Here is the title of the news',
'body' => 'Here is the news body',
'source' => 'News came from here'
)
);
$news = $this->News->submit('product-1', 'user-1', $newsData);
// Now what?
}
Simply assert that $news is an array, object, that the array is equal to an array you expect... Whatever your method returns, you should know it even before implementing the method (test driven development) and be able to assert the result using one or more than one of the phpunit assert methods.
Like simply $this->assertTrue($news); Check the manual for all the asserts. http://www.phpunit.de/manual/current/en/
Also look at the CakePHP core tests to get an idea of how to do test.
Or look at some open source plugin exmaples like
https://github.com/CakeDC/tags/blob/2.0/Test/Case/Model/TaggedTest.php
or
https://github.com/CakeDC/users/blob/2.0/Test/Case/Model/UserTest.php

How to perform complex searches and test them, in cakePHP and Simpletest

I have a very complex data structure, something like 10 tables without the join tables. My application needs to be able to perform search in most of the tables.
To do this, I though to turn the content of the search fields into an array of conditions. The key is the model name, the value is the search conditions, i.e.
$conditions = array(
'Artist' => array(
'OR' => array(
'Artist.name LIKE' => '%barl%',
'Pseudonym.name LIKE' => '%barl%'
)
),
'Content' => array('Content.subject' => 'architecture'),
'Editor' => array('Editor.name LIKE' => '%Gal%'),
etc....
)
This array gets passed to the models that are searchable and each model takes the condition that is relevant.
$this->find('all', array('conditions' => $conditions['Artist']))
So far so good, at least I think. Now I started to test the models and I found myself copying over and over that same array in the different model test cases, and that bothers me.
Is there a way to have this array accessible to every test cases? Maybe the array is not the best solution and I should make a search model?
Any suggestions?
Put the array as property in the app_model.php as something like $commonSearchConditions and access them from inside your models which should inherit the AppModel.
Depending on what exactly you do, if the searches differ in every model, I would have a test-case in every models test. If not you might want to create a separate test with a test model you create inside of the test for testing just the search stuff you want to do. Hard to tell without knowing more.

Adding validates_uniqueness_of to a model fails functional tests

Trying to make a simple application in rails 3.
If I create a team model with rails g scaffold team name:string && rake db:migrate, then run rake, I get success from the prebuilt tests.
If I simply add validates_uniqueness_of :name to the team model. The functional tests fail with
1) Failure:
test_should_create_team(TeamsControllerTest) [/test/functional/teams_controller_test.rb:20]:
"Team.count" didn't change by 1.
<3> expected but was
<2>.
I modified tests/fixtures/teams.yml to look like this:
one:
name: MyString
two:
name: MyString2
The test still fails.
It can't get much more basic than this; what have I missed?
Fixtures basically represent model instances that are in the database.
If you look at the top of test/functional/teams_controller_test.rb you'll see
setup do
#team = teams(:one)
end
and then in your failing functional test you'll have
post :create, :team => #team.attributes
This is what's happening: you're trying to create a new team with the same attributes as "the team fixture named :one". Since both would have the same name (since they have the exact same attributes), the uniqueness validation is failing.
Try replacing your setup block with this
setup do
#team = teams(:one)
#team.name = 'unique name'
end
Now you'll be creating a new team with the name 'unique name' (which isn't in the database according to the fixtures), and your test will pass.