In my angular 2 app, How do I test if my external method (dependency) inside my main method is being called accordingly.
For instance,
Class ServiceA
{
constructor(
private serviceB : ServiceB
){}
//How do I test this method to make sure it does what it should ?
mainMethod()
{
//External method
this.serviceB.otherMethod();
this.sideMethod();
}
sideMethod()
{
//Do something
}
}
Class ServiceB
{
constructor(){}
otherMethod()
{
//Do something
}
}
Here's what I've tried so far
it('On otherMethod returns false, do something',
inject([ServiceA, ServiceB], (serviceA: ServiceA, serviceB: ServiceB) => {
spyOn(serviceB, 'otherMethod').and.returnValue(false);
spyOn(serviceA, 'sideMethod');
spyOn(serviceA, 'mainMethod').and.callThrough();
expect(serviceB.otherMethod()).toHaveBeenCalled();
expect(serviceA.sideMethod()).toHaveBeenCalled();
expect(serviceA.mainMethod()).toHaveBeenCalled();
}));
From above code, I got an error stating
could not find an object to spy upon for otherMethod()
What is wrong here ?
You have to pass the function reference of your spy serviceB.otherMethod. You are currently invoking the spy by calling serviceB.otherMethod() which will return the return value of otherMethod instead of the spy.
it('On otherMethod returns false, do something',
inject([ServiceA, ServiceB], (serviceA: ServiceA, serviceB: ServiceB) => {
spyOn(serviceB, 'otherMethod').and.returnValue(false);
spyOn(serviceA, 'sideMethod');
spyOn(serviceA, 'mainMethod').and.callThrough();
// Notice spy reference here instead of calling it.
expect(serviceB.otherMethod).toHaveBeenCalled();
expect(serviceA.sideMethod).toHaveBeenCalled();
expect(serviceA.mainMethod).toHaveBeenCalled();
}));
Jasmine documentation: https://jasmine.github.io/2.0/introduction.html#section-Spies
Related
in my code i have a lookup method:
lookup.dart
Future<http.Response> httpLookup(String address) {
return kIsWeb
? _httpClient.get(address)
: _httpClient.get(
Uri.https(address, ''),
);
}
how can i test the kIsWeb constant during unit testing? this is what i have tried so far but the coverage is not going though.
lookup_test.dart
#TestOn('browser')
void main (){
test('shoud test lookup', () {
InternetLookup lookup = InternetLookup();
when(mockInternetLookup.httpLookup(any))
.thenAnswer((realInvocation) async => http.Response('success', 200));
lookup.httpLookup('www.google.com');
});
}
You can to use an Interface and to mock it.
abstract class IAppService {
bool getkIsWeb();
}
class AppService implements IAppService {
bool getkIsWeb() {
return kIsWeb;
}
}
In the tests, you must to use like as
class MockAppService extends Mock implements IAppService {}
...
when(appService.getkIsWeb())
.thenAnswer((realInvocation) => true);
Another way would be to actually run it in a web environment with
flutter test --platform chrome
You can also add
#TestOn('browser')
at the top of your test file so your tests are only run when the platform is a browser.
Look at TestOn and its README.
Another way would be to add an optional parameter and decorate it with #visibleForTesting to override the kIsWeb constant:
Future<http.Response> httpLookup(String address, { #visibleForTesting bool isTestingForWeb = false}) {
return kIsWeb || isTestingForWeb ? ...
}
Roughly, my JavaScript function that I want to unit-test looks like this:
const request = require('request-promise-native');
async function callServer() {
// Prepare parameters
// Call `request` with parameters
// Parse response JSON and return
}
Is there any way to unit-test this function without making an actual call to the real server? Can I use a jest mock function to somehow override request()? To do that, will I need to modify every function to take the request function as a parameter or there is another way?
You can mock imported module via jest.mock. https://jestjs.io/docs/en/api#requirerequiremockmodulename
describe('main description', () => {
it('description of test case', () => {
jest.mock('request-promise-native', () => {
return {}; // Return what the request-promise-native supposed to return
});
const result = callServer();
expect(result).toBe({});
});
});
I have problem unit testing method inside closure called by call_user_func() example :
public function trans($lang, $callback)
{
$this->sitepress->switch_lang($lang);
call_user_func($callback);
}
on controller :
public function sendMail()
{
$foo = $baz = 'something';
$mail = $this->mailer;
$this->helper->trans_c('en', function() use($foo, $baz, $mail) {
$mail->send('Subject', $foo, $baz);
});
}
test case :
public function testSomething()
{
$helperMock = Mockery::mock('Acme\Helper');
$helperMock->shouldReceive('trans_c')->once(); // passed
$mailMock = Mockery::mock('Acme\Mail');
$mailMock->shouldReceive('send')->once(); // got should be called 1 times instead 0
$act = new SendMailController($helperMock, $mailMock);
$act->sendMail();
}
how can I ensure that ->send() method is called inside closure trans_c()
I tried with
$helperMock->shouldReceive('trans_c')->with('en', function() use($mailMock) {
$mailMock->shouldReceive('send');
});
no luck. :(
well it works fine with passing Mockery::type('Closure') in the second param of trans_c, but I really need to ensure that method send from mailer class is called.
A mocked class does not execute the real code by default. If you mock the helper it will check that the calls are being made but won't execute the anonymous function.
With mockery, you can configure the expectation so that the real method will be executed: passthru();
Try this:
$helperMock = Mockery::mock('Acme\Helper');
$helperMock
->shouldReceive('trans_c')
->once()
->passthru()
;
This is explained in the docs.
EDIT
Maybe you don't really need to mock the helper. If you mock the Mail class and expect the send method to be called once, just let the real helper do it.
I have a question about routing while testing packages. The function setRoutes creates new routes in the test file as follows:
class PackageTests extends \Orchestra\Testbench\TestCase {
protected function setRoutes()
{
Route::group([
'prefix' => Package::functionToCall1(),
'before' => 'filter'
], function() {
Route::get('/', function () {
return "hello";
});
});
Route::enableFilters();
}
protected function getEnvironmentSetUp($app)
{
$this->app = $app;
$this->setRoutes();
Config::set('app.url', "http://localhost/" );
}
public function testFunction1()
{
$crawler = $this->call(
'GET',
'http://localhost/'
);
// doing this call, the function on the prefix is called
$this->assertResponseOk();
}
}
Inside the function called in the prefix, functionToCall1() urls are not taken successfully. A call to URL::current() returns "/" and a call to Request::fullUrl() returns "http://:" when phpunit is executed but they returns the full url when used executing a url in the browser. This is the code of the package:
class Package
{
function functionToCall1()
{
var_dump(URL::current() ); // returns "/"
var_dump(Request::fullUrl()); // returns "http://:"
// I want them to return 'http://localhost'
}
}
I tried setting up the url Config::set('app.url', "http://localhost/" ); but it was useless.
To sum up, is there a way to call a function in the prefix and get the testing url?
Thanks, I would really appreciate your answers :)
I have had to deal with a similar issue. My solution was found here:
Mocking Laravel's Request::segment method
Apparently there is an order of operations issue with testing a Request facade.
I was trying to use Request::segments() before the request was being built, so there were never any segments to return.
I imagine it's the same problem with Request::fullUrl().
Here is my solution:
class MyTestClass extends TestCase
{
public function setUp()
{
// No call to parent::setUp()
$this->app = $this->createApplication();
$this->app->request->server->set('REQUEST_URI', '/some/uri');
$this->client = $this->createClient();
$this->app->boot();
}
public function testWhatever()
{
$this->call('GET', '/some/uri');
}
}
This allows me to get the request data properly, even though it looks pretty bad.
I am trying to mock my class that is under test, so that I can callbase on individual methods when testing them. This will allow me to test the method setup as callbase only, and all other methods (of the same class) called from within the test method will be mocked.
However, I am unable to do this for the methods that do not return a value. The intellisense just doesn't display the option of callbase, for methods that do not return value.
Is this possible?
The Service Class:
public class Service
{
public Service()
{
}
public virtual void StartProcess()
{
//do some work
string ref = GetReference(id);
//do more work
SendReport();
}
public virtual string GetReference(int id)
{
//...
}
public virtual void SendReport()
{
//...
}
}
Test Class setup:
var fakeService = new Mock<Service>();
fakeService.Setup(x => x.StartProcess());
fakeService.Setup(x => x.GetReference(It.IsAny<int>())).Returns(string.Empty);
fakeService.Setup(x => SendReport());
fakeService.CallBase = true;
Now in my test method for testing GetReference I can do this:
fakeService.Setup(x => x.GetReference(It.IsAny<int>())).CallBase();
but when i want to do the same for StartProcess, .CallBase is just not there:
fakeService.Setup(x => x.StartProcess()).CallBase();
it becomes available as soon as i make the method to return some thing, such a boolean value.
First of all, your mock will not work because methods on Service class are not virtual. When this is a case, Moq cannot intercept calls to insert its own mocking logic (for details have a look here).
Setting mock.CallBase = true instructs Moq to delegate any call not matched by explicit Setup call to its base implementation. Remove the fakeService.Setup(x => x.StartProcess()); call so that Moq can call base implementation.