I'm trying to fix this issue https://github.com/dotnet-security-guard/roslyn-security-guard/issues/60 Affected file is https://github.com/dotnet-security-guard/roslyn-security-guard/blob/master/RoslynSecurityGuard/Analyzers/CsrfTokenAnalyzer.cs
There is DiagnosticAnalyzer implemented and the logic in VisitMethods(SyntaxNodeAnalysisContext ctx) method is not correct for API method. So that I want to add such check to that method to exclude all the controller methods which return ViewResult instance as API method will not return a view.
Can you suggest me how can I traverse a C# (and VB) method body and find if a body contains any statement which returns ViewResult instance?
Call .DescendantNodes() on the method's node and filter for all return statements.
For each return statement you find, check whether .Expression (which may not exist)'s TypeSymbol (from the semantic model) is / is convertible to ViewResult.
To handle expression-bodied members, do the same check for ArrowExpressionClause.
Related
All the examples of jest and jest-fetch-mock I have come across use functions that perform an API query and return a payload directly from the function call.
In my case, I have a different setup. I have a class that has a property called 'data'. In the class there is a method called "get" which pulls data using fetch API and stores it in the data property. When the method is called, it simply returns true or false based on promise resolve or reject.
I am trying to figure out how to write unit tests for this in this case. My function doesn't return the data fetched; only a boolean value.
So if I use jestSpyOn to mock the class method, how would I set the data property, and then retrieve the result?
In my code, I do something like this (NOT in testing, but in the actual app):
contactStore = new ContactListStore();
// 'all' is a sample param passed
contactStore.get('all').then(res => {
if(res){
...perform action
}
});
As you can see the res argument is only boolean, and if true, then contactStore.data will contain the information retrieved from the server.
So to run a unit test on it, I need to call a mock get, and set a mock data property.
Any ideas how this would be done?
In your mock method, you just need return true.
I was looking at the documentation at: https://pub.dartlang.org/packages/mockito and was trying to understand it more. It seems that in the examples, the function stubs were accepting strings, but was kind of confused as to how I was going to implement my Mocked Services.
I was curious how I would do it. The services I have is pretty simple and straight forward.
class Group{}
class GroupService {}
class MockGroupService extends Mock implements GroupService {}
final mockProviders = [new Provider(MockGroupService, useExisting: GroupService];
So you can see I am using Angular dart.
I was creating a sample group in my Test file.
group("service tests", (){
MockGroupService _mock;
testBed.addProviders([mockProviders]);
setUp(() async {
fixture = await testBed.create();
_mock = new MockGroupService();
//This is where I was going to create some stubbs for the methods
when(_mock.add()).thenReturn((){
return null; //return the object.
});
//create additional when statements for edit, delete, etc.
});
});
So what i was thinking is that there would be an argument passed into add (or 2).... how would I properly code that in the when statement, and how do those 2 arguments reflect in the then statement?
Essentially, I was wanting to do a test with a complex class.. and pass it into add. Then it would just process it accordingly and return it.
Do i pass into the arguments something akin to: (using pseudocode)
when(_mock.add(argThat(hasType(Group)))).thenReturn((Group arg)=> arg);
or something similar? hasType isnt function, so im not 100% sure how to approach this design. Ideally, Im trying create the Group in the test, and then pass it into the add function accordingly. It just seems that the examples were showing Strings.
Yes mockito allows objects to be passed you can see examples in the test.
It is a bit hard to follow but you can see here that it uses deep equality to check if arguments are equal if no matchers are specified.
The second part of your question is a bit more complex. If you want to use the values that were passed into your mock as part of your response then you need to use thenAnswer. It provides you with an Invocation of what was just called. From that object you can get and return any arguments that were used in the method call.
So for your add example if you know what is being passing in and have complete access to it I would write:
Group a = new Group();
when(_mock.add(a)).thenReturn(a);
If the Group object is being created by something else I would write:
when(_mock.add(argThat(new isInstanceOf<Group>()))
.thenAnswer((invocation)=>invocation.positionalArguments[0]);
Or if you don't really care about checking for the type. Depending on what checks you are using for your test the type might already be checked for you.
when(_mock.add(any)).thenAnswer(
(invocation)=>invocation.positionalArguments[0]);
Or if you are using Dart 2.0:
when(_mock.add(typed(any))).thenAnswer(
(invocation)=>invocation.positionalArguments[0]);
I'm mocking my repository correctly, but in cases like show() it either returns null so the view ends up crashing the test because of calling property on null object.
I'm guessing I'm supposed to mock the eloquent model returned but I find 2 issues:
What's the point of implementing repository pattern if I'm gonna end up mocking eloquent model anyway
How do you mock them correctly? The code below gives me an error.
$this->mockRepository->shouldReceive('find')
->once()
->with(1)
->andReturn(Mockery::mock('MyNamespace\MyModel)
// The view may call $book->title, so I'm guessing I have to mock
// that call and it's returned value, but this doesn't work as it says
// 'Undefined property: Mockery\CompositeExpectation::$title'
->shouldReceive('getAttribute')
->andReturn('')
);
Edit:
I'm trying to test the controller's actions as in:
$this->call('GET', 'books/1'); // will call Controller#show(1)
The thing is, at the end of the controller, it returns a view:
$book = Repo::find(1);
return view('books.show', compact('book'));
So, the the test case also runs view method and if no $book is mocked, it is null and crashes
So you're trying to unit test your controller to make sure that the right methods are called with the expected arguments. The controller-method fetches a model from the repo and passes it to the view. So we have to make sure that
the find()-method is called on the repo
the repo returns a model
the returned model is passed to the view
But first things first:
What's the point of implementing repository pattern if I'm gonna end up mocking eloquent model anyway?
It has many purposes besides (testable) consisten data access rules through different sources, (testable) centralized cache strategies, etc. In this case, you're not testing the repository and you actually don't even care what's returned, you're just interested that certain methods are called. So in combination with the concept of dependency injection you now have a powerful tool: You can just switch the actual instance of the repo with the mock.
So let's say your controller looks like this:
class BookController extends Controller {
protected $repo;
public function __construct(MyNamespace\BookRepository $repo)
{
$this->repo = $repo;
}
public function show()
{
$book = $this->repo->find(1);
return View::make('books.show', compact('book'));
}
}
So now, within your test you just mock the repo and bind it to the container:
public function testShowBook()
{
// no need to mock this, just make sure you pass something
// to the view that is (or acts like) a book
$book = new MyNamespace\Book;
$bookRepoMock = Mockery::mock('MyNamespace\BookRepository');
// make sure the repo is queried with 1
// and you want it to return the book instanciated above
$bookRepoMock->shouldReceive('find')
->once()
->with(1)
->andReturn($book);
// bind your mock to the container, so whenever an instance of
// MyNamespace\BookRepository is needed (like in your controller),
// the mock will be loaded.
$this->app->instance('MyNamespace\BookRepository', $bookRepoMock);
// now trigger the controller method
$response = $this->call('GET', 'books/1');
$this->assertEquals(200, $response->getStatusCode());
// check if the controller passed what was returned from the repo
// to the view
$this->assertViewHas('book', $book);
}
//EDIT in response to the comment:
Now, in the first line of your testShowBook() you instantiate a new Book, which I am assuming is a subclass of Eloquent\Model. Wouldn't that invalidate the whole deal of inversion of control[...]? since if you change ORM, you'd still have to change Book so that it wouldn't be class of Model
Well... yes and no. Yes, I've instantiated the model-class in the test directly, but model in this context doesn't necessarily mean instance of Eloquent\Model but more like the model in model-view-controller. Eloquent is only the ORM and has a class named Model that you inherit from, but the model-class as itself is just an entity of the business logic. It could extend Eloquent, it could extend Doctrine, or it could extend nothing at all.
In the end it's just a class that holds the data that you pull e.g. from a database, from an architecture point of view it is not aware of any ORM, it just contains data. A Book might have an author attribute, maybe even a getAuthor() method, but it doesn't really make sense for a book to have a save() or find() method. But it does if you're using Eloquent. And it's ok, because it's convenient, and in small project there's nothing wrong with accessing it directly. But it's the repository's (or the controller's) job to deal with a specific ORM, not the model's. The actual model is sort of the outcome of an ORM-interaction.
So yes, it might be a little confusing that the model seems so tightly bound to the ORM in Laravel, but, again, it's very convenient and perfectly fine for most projects. In fact, you won't even notice it unless you're using it directly in your application code (e.g. Book::where(...)->get();) and then decide to switch from Eloquent to something like Doctrine - this would obviously break your application. But if this is all encapsulated behind a repository, the rest of your application won't even notice when you switch between databases or even ORMs.
So, you're working with repositories, so only the eloquent-implementation of the repository should actually be aware that Book also extends Eloquent\Model and that it can call a save() method on it. The point is that it doesn't (=shouldn't) matter if Book extends Model or not, it should still be instantiable anywhere in your application, because within your business logic it's just a Book, i.e. a Plain Old PHP Object with some attributes and methods describing a book and not the strategies how to find or persist the object. That's what repositories are for.
But yes, the absolute clean way is to have a BookInterface and then bind it to a specific implementation. So it could all look like this:
Interfaces:
interface BookInterface
{
/**
* Get the ISBN.
*
* #return string
*/
public function getISBN();
}
interface BookRepositoryInterface()
{
/**
* Find a book by the given Id.
*
* #return null|BookInterface
*/
public function find($id);
}
Concrete implementations:
class Book extends Model implements BookInterface
{
public function getISBN()
{
return $this->isbn;
}
}
class EloquentBookRepository implements BookRepositoryInterface
{
protected $book;
public function __construct(Model $book)
{
$this->book = $book;
}
public function find($id)
{
return $this->book->find($id);
}
}
And then bind the interfaces to the desired implementations:
App::bind('BookInterface', function()
{
return new Book;
});
App::bind('BookRepositoryInterface', function()
{
return new EloquentBookRepository(new Book);
});
It doesn't matter if Book extends Model or anything else, as long as it implements the BookInterface, it is a Book. That's why I bravely instantiated a new Book in the test. Because it doesn't matter if you change the ORM, it only matters if you have several implementations of the BookInterface, but that's not very likely (sensible?), I guess. But just to play it safe, now that it's bound to the IoC-Container, you can instantiate it like this in the test:
$book = $this->app->make('BookInterface');
which will return an instance of whatever implementation of Book you're currently using.
So, for better testability
Code to interfaces rather than concrete classes
Use Laravel's IoC-Container to bind interfaces to concrete implementations (including mocks)
Use dependency injection
I hope that makes sense.
I want to test the in case of some fail no method will be called on a mock object , using google mock.
so the code be something like:
auto mocObj = new MockObj;
EXPECT_NO_METHOD_CALL(mocObj); //this is what I'm locking for
auto mainObj = new MainObj(mocObj , ......and other mocks); // here I simulate a fail using the other mock objects, and I want to be sure the no methods are called on the mockObj
There are no needs to explicitly tell that no methods will be called. If you set the logging level high enough, you should get a message if a method is called (if no expectation is set).
Other then that, you can set expectations like this :
EXPECT_CALL( mockObj, Foo(_) ).Times(0);
on all methods.
Create a StrictMock; any unexpected method call will be a failure.
Use Exactly(0) for all your class methods.
the cardinality will be set to zero so you are expecting no calls
You can also use StrictMock instead of NiceMock. This will fail on any "uninteresting" call, i.e., whenever a method of the mock is called, but no EXPECT_CALL was defined.
See Google Mock documentation here.
I'm calling a method of a library that I've created in symfony 1.2. If I don't call the library method in the action method, then the method in the action class works as it should, and it finds the template. But, if I call the library method in the action class, symfony tells me that it cannot find the template associated to the action method. Any suggestions?
Did you try return sfView::NONE on your action code?
Returning sfView::NONE is telling Symfony to display nothing. The explicit return value sounds like the right approach but you probably want:
return sfView::SUCCESS;