Flutter Unit Test for Create Constructor - flutter

My question is: How can I run the test aiming to test de loadSpecies() called inside constructor initialize?
Class
class TodoProvider with ChangeNotifier {
TodoProvider() {
loadSpecies();
}
loadSpecies() {
/* Here is the request to API */
}
}
Test
What I need to do here?
test('Initialization', () async {
when(EstablishmentProvider());
});

Inside when you will have to mock the api request which you will be doing in loadSpecies() method.
Lets you are getting http client object inside your constructor like this:
class TodoProvider with ChangeNotifier {
final Client client;
TodoProvider(this.client) {
loadSpecies();
}
loadSpecies() {
/* Here is the request to API */
}
}
To mock the api, you will have create mock class of your http client.
class MockClient extends Mock implements Client {}
and then initialise an object of the MockClient
final client = MockClient();
Then, mock the api using client variable
when(()=> client.get(any()).thenAnswer(() async => \* return whatever object */);
To test the output of your method loadSpecies(), you can use expect() method

Related

How to verify a method inside a method is called in mockito

I was doing some unit testing in flutter with mockito, and I feels unable to verify a method is called within another method. The code I've written so far as follows,
The class I want to test
class A {
void doSomething() {
callMe();
}
void callMe() {}
}
Mocked class
class MockA extends Mock implements A {}
The test I wrote,
test("Test method is called", () {
A a = new MockA();
a.doSomething();
verify(a.callMe()).called(1);
});
When I run the above test I am getting an error
No matching calls. All calls: MockA.doSomething()
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)
If i verify doSomething is called it works, but for a call on callMe within doSomething doesn't work. Is this the default behavior or am I doing something wrong? Please note I need to verify the callMe() method is called when doSomething() is called.
You mocked A and replaced it with MockA. Mocks have no implementation. MockA.doSomething() does nothing and does not and cannot call MockA.callMe().
That A.doSomething() calls A.callMe() should be considered an implementation detail of of doSomething(); making a test rely on that would tightly couple the test to the specific implementation and would be brittle.
You can't use a mock to verify the implementation of the thing being mocked. If you want to verify the implementation of A.doSomething(), you instead should use an actual object and verify observable properties on that object.
But if you still really want to do this, then you would need to modify A to not call methods on itself and to instead call methods on a provided object (i.e., "dependency injection"). For example:
class A {
final late A a;
A({A? a}) {
this.a = a ?? this;
}
void doSomething() {
a.callMe();
}
void callMe() {}
}
test("Test method is called", () {
var mockA = MockA();
var actualA = A(a: mockA);
actualA.doSomething();
verify(mockA.callMe()).called(1);
});
It's a bit unusual for a class to depend on a mock of itself, however, and it would not scale if you then want to verify calls made by callMe().
Another approach that would scale better (but with significantly more work) would be to create your own fake class that tracks method calls:
class TrackedA implements A {
int doSomethingCallCount = 0;
int callMeCallCount = 0;
#override
void doSomething() {
doSomethingCallCount += 1;
super.doSomething();
}
#override
void callMe() {
callMeCallCount += 1;
super.callMe();
}
}
But again, that's very brittle, and I would not recommend it.

Inject service or class in guard in NestJS

Needs to DI Kafka client in guard:
auth.guard.ts
export class AuthGuard implements CanActivate {
private _client: ClientKafka; <----- // TODO implement nestjs DI mechanism
public async canActivate(context: ExecutionContext): Promise<boolean> {
try {
const request = context.switchToHttp().getRequest();
const authorization: string = request.get('Authorization');
...code here just send data to jwt service...
return true;
} catch (err) {
return false;
}
}
}
I use new in canActivate for creating an instance of Kafka client in auth.guard.ts. But how to inject a class in guard with #Inject? I used to create #Global module, which provides and export Kafka client class, but it's not working...
Use This in the module for globally using the guard
providers: [{provide: APP_GUARD, useClass: AuthGuard}]
As for your question about injecting a class inside a guard, you need to inject it inside the constructor of the AuthGuard class
export class AuthGuard implements CanActivate {
constructor(private clientKafka : ClientKafka){}
}
if this doesn't work, try using
constructor(#Inject(private clientKafka : ClientKafka)){}
Hope this resolves your issue :)

Micronaut: Test POST request

In my Micronaut app I have a simple REST controller:
public class Response {
private String code;
public Response(String code) {
this.code = code;
}
}
#Controller("/api/test")
public class TestController {
#Post("/")
public Response index() {
return new Response("OK");
}
}
How can I tests this edpoint? I tried using
#MicronautTest
public class TestControllerTest {
#Inject
EmbeddedServer server;
#Inject
#Client("/")
HttpClient client;
#Test
void testResponse() {
String response = client.toBlocking()
.retrieve(HttpRequest.POST("/api/test/")); // FIXME `HttpRequest.POST` requires body
assertEquals("{\"code\": \"OK\"}", response);
}
but HttpRequest.POST requires an additional body argument to be specified. In my case there is no body to be sent. (In the real code it is a request to initialize a new object and thus it has to be POST).
Usually, when you implement a POST action, you expect that there is a body sent with the request. In your example, you don't accept any POST body, but you still need to pass anything in the unit test.
You can instantiate the HttpRequest object in the following way:
HttpRequest.POST("/api/test/", "");
You can't pass null, it has to be some non-null value (like an empty string.)

Print data received by REST call when using #Resource in Grails

Following along with groovies docs on REST, i've setup a model like so:
import grails.rest.*
#Resource(uri='/books')
class Book {
String title
static constraints = {
title blank:false
}
}
I'd print out the parameters I receive when creating and saving. Is there away to override these methods created by the #Resource(uri='/books') annotation? Or handle the annotation a closure or something to do this?
I think you may have 2 choices if you wish to have a default RESTful interface and modify it somewhat for your needs.
Use the $ grails generate-controller [Domain Class Name] command that will generate the appropriate controller and change the generated file as needed.
Create a Book controller and extend the RestfulController; then override the default methods with the #Override annotation, print/log the params, and then call the matching super method.
import grails.rest.RestfulController
class BookController extends RestfulController {
static responseFormats = ['json', 'xml']
BookController() {
super(Book)
}
#Override
def save() {
println params
super.save params
}
#Override
def update() {
println params
super.update params
}
}

How to mock a RemoteServiceServlet with HttpRequestSession

Here is a code snippet of my RemoteServiceServlet. The function getSubject(), obtains the session from the HttpServletRequest, which refers to the getThreadLocalRequest. I am making a junit test to test this server, however the getThreadLocalRequest is not populated and returns null.
public class Server extends XsrfProtectedServiceServlet implements RemoteInterface {
private static final long serialVersionUID = 2230123191888380541L;
public Server() throws IOException
{
credentials = new PropertiesCredentials(Server.class.getResourceAsStream("AwsCredentials.properties.email"));
database = new Database();
}
public Subject getSubject()
{
HttpServletRequest request = this.getThreadLocalRequest();
HttpSession session = request.getSession(false);
Subject subject = (Subject)session.getAttribute("subject");
return subject;
}
}
This is my junit test
#Test
public void testserver()
{
Server s = new Server();
s.getSubject();
}
s.getSubject fails because the session is not populated. How can I mock Server so that I can populate a session.
You'll need to use a mocking framework to create behaviour around the object under test. I use PowerMock with EasyMock (http://code.google.com/p/powermock/).
What I suggest you do first, though, is refactor the code out of the constructor. As written, this code is very complicated to test, because the getResourceAsStream method is a static method of the underlying Class type. And since it's not used in the method under test (nor is the database reference), I question the need to use the constructor to get the resource bundle.
To test your getSubject() method, essentially what you need to do is create an instance of your class that is a partial mock, where the getThreadLocalRequest is the only method to be mocked:
#RunWith( PowerMockRunner.class )
#PrepareForTest( Server.class )
public class ServerTest {
#Test
public void testGetSubjectReturnsSubjectFromHttpSession() {
// assuming the constructor is cleaned up, create a Server instance...
Server server = PowerMock.createPartialMockAndInvokeDefaultConstructor( Server.class, "getThreadLocalRequest" );
// create a mock object that represents the Http request
HttpServletRequest mockRequest = PowerMock.createMock(HttpServletRequest.class);
EasyMock.expect( server.getThreadLocalRequest() ).andReturns( mockRequest);
// create a mock for the Http Session
HttpSession mockSession = PowerMock.createMock( HttpSession.class );
EasyMock.expect( mockRequest.getSession( EasyMock.anyBoolean() ) ).andReturns( mockSession );
EasyMock.expect( mockSession.getAttribute( EasyMock.isA( String.class ) ).andReturns( mockSubject );
// put the mocks into playback mode
PowerMock.replayAll();
// exercise the method
Subject subject = server.getSubject();
// verify that the mocks were called as you expect them to be...
PowerMock.verifyAll();
// and here you put other assertions that relate to the data returned...
Assert.assertNotNull( subject );
}
}