Jest unit-testing if super() is called - unit-testing

I have a custom error class that extends the built-in Error class in Javascript. The problem I came up with is that "super()" method is not checked if it is called or not through my Jest unit testing.
export class AppError extends Error {
public name: string;
public message: string;
public status?: number;
public data?: any;
constructor(message: string, status?: number, data?: any) {
super(); <-- this guy!!
this.name = 'AppError';
this.status = status || 500;
this.message = message;
this.data = data;
}
}
Is there any way to test it? Thanks.

There's no reason to check if super() is called neither in native ES6 classes nor in classes transpiled with Babel.
Not calling super in child class constructor will result in error on class instantiation:
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
Babel provides a safeguard for that as well:
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
It may be possible to check that parent constructor is called (could be useful to assert super() arguments) by mocking child class prototype, something like:
let ParentOriginal;
let ParentMock;
beforeEach(() => {
ParentOriginal = Object.getPrototypeOf(AppError);
ParentMock = jest.fn();
Object.setPrototypeOf(AppError, ParentMock);
});
it('..', () => {
new AppError(...);
expect(ParentMock.mock.calls.length).toBe(1);
})
afterEach(() => {
Object.setPrototypeOf(AppError, ParentOriginal);
});
It's expected to mock super in both native classes and classes transpiled with Babel.
But this test is redundant, because missing super() will result in error any way. Testing that AppError inherits from Error is everything that needs be tested here:
expect(new AppError(...)).toBeInstanceOf(Error)

Related

FakeItEasy - I cannot see if a protected method was called when the caller method is protected overriden

I'm new to FakeItEasy, sorry if the solution is obvious.
This is the simplified code which reproduces the problem:
I have a base class:
public abstract class BaseClass
{
public void Do()
{
Do_Override();
}
protected abstract void Do_Override();
}
and a derived one:
public class ImplementingClass: BaseClass
{
protected override void Do_Override()
{
ProtectedDo();
}
protected virtual void ProtectedDo()
{
}
}
In my test I want to see if ProtectedDo() was called. I've tried to test in two ways, but tests are failing with the same message:
1st. In debug mode it is not entering in Do_Override()
public class ImplementingClassShould
{
[Fact]
public void Run_ProtectedDo()
{
var fake = A.Fake<ImplementingClass>();
fake.Do();
A.CallTo(fake).Where(_ => _.Method.Name == "ProtectedDo").MustHaveHappened();
}
}
2nd. In debug mode it is entering in Do_Override()
public class ImplementingClassShould
{
[Fact]
public void Run_ProtectedDo_V2()
{
var sut = new ImplementingClass();
var sutFakeWrapper = A.Fake<ImplementingClass>(_ => _.Wrapping(sut));
sutFakeWrapper.Do();
A.CallTo(sutFakeWrapper).Where(_ => _.Method.Name == "ProtectedDo").MustHaveHappened();
}
}
Fail message:
Your test is perfectly good, as far as it goes. If you run it, it'll tell you that ProtectedDo was not called, which is accurate. Because Do_Override is virtual, FakeItEasy intercepts the call. (The protectedness doesn't affect things in this case.)
If you don't want Do_Override to be intercepted by FakeItEasy, you should configure the Fake to call the base method instead of handling the call itself:
[Fact]
public void Run_ProtectedDo()
{
var fake = A.Fake<ImplementingClass>();
A.CallTo(fake).Where(_ => _.Method.Name == "Do_Override").CallsBaseMethod();
fake.Do();
A.CallTo(fake).Where(_ => _.Method.Name == "ProtectedDo").MustHaveHappened();
}
Update in light of the newly added Run_ProtectedDo_V2 test:
I expect you know this already, #fmm, but the test still fails. This is because when sutFakeWrapper.Do is called, it forwards to the wrapped sut.Do. Since sut is a concrete ImplementingClass, it calls its Do_Override, which calls its ProtectedDo, so it's possible to debug into a ProtectedDo method call. Only it's sut.ProtectedDo, not sutFakeWrapper.ProtectedDo. Hence the test failure.

flutter: unit testing dao in moor

I've started unit testing the first time. I'm following tutorials of resoCoder
here is my test code where I'm mocking my dbManager class but I could not mock DAO's as they are auto-generated in moor and there is no setter method for them.
class MockDbManager extends Mock implements DbManager{}
void main() {
RecipeLocalDataSource dataSource;
MockDbManager _dbManager;
setUp(() {
_dbManager = MockDbManager();
dataSource = RecipeLocalDataSource(_dbManager);
});
group('Search Food Table', (){
List<FoodTableData> getFoodTable(){
var list = [];
for(var i =1; i <=5 ; i++){
list.add(FoodTableData(id: i, name: 'item $i'));
}
return list;
}
var searchQuery = 'query';
test('Should return foodTableData when query is successful', (){
//arrange
when(_dbManager.foodTableDao.searchFoods(searchQuery)).thenAnswer((realInvocation) async => getFoodTable());
//act
var result = dataSource.searchFoodTable('test');
//assert
verify(_dbManager.foodTableDao.searchFoods(searchQuery));
expect(getFoodTable(), result);
});
});
}
I'm getting the following error
NoSuchMethodError: The method 'searchFoods' was called on null.
Receiver: null
Tried calling: searchFoods("query")
I understood the error but don't know how to solve that.
Also, I'm getting a similar issue with preferenceManager class as well, where I'm having a getter for UserPrefs.
UserPrefs get user => UserPrefs(_pref);
when I'm accessing _prefManager.user.name for the test, it throws the same error. How can I tackle that as well?
I believe you're missing a level of mocking, leading to the null exception. Keep in mind the mocked class returns null for everything. You have to provide values for everything.
You've mocked DbManager, but not the foodTableDao field inside DbManager.
// I don't have your classes, so these are just my guesses at matching their interface
abstract class TableDao {
String searchFoods();
}
abstract class DbManager {
TableDao foodTableDao;
}
class MockDbManager extends Mock implements DbManager {}
class MockTableDao extends Mock implements TableDao {}
// ↑ Define this mocked class as well
void main() {
test('Mockito example', () {
final dbManager = MockDbManager();
final mockTableDao = MockTableDao();
// ↑ instantiate this mocked class which will be a field value inside dbManager
// Mock the field access for dbManager.foodTableDao
when(dbManager.foodTableDao).thenReturn(mockTableDao);
// ↑ You're missing this ↑ level of stubbing, so add this
when(mockTableDao.searchFoods()).thenAnswer((realInvocation) => 'Cucumber');
// ↑ define the stubbing at the mockTableDao level, not dbManger.mockTableDao.searchFoods
expect(dbManager.foodTableDao.searchFoods(), 'Cucumber');
// You can use foodTableDao field here, getting the mocked value as expected
});
}
In your example above, you can't access dbManager.foodTableDao to set up a mock for dbManager.foodTableDao.searchFoods(), because dbManager.foodTableDao is null until you mock it. So this line:
when(_dbManager.foodTableDao.searchFoods(searchQuery)).thenAnswer((realInvocation) async => getFoodTable());
was throwing the null exception, not the expect test below. (The expect test was never reached.)
The issue with _prefManager.user.name is the same I'm guessing. You need to mock User class and provide a when/return of MockUser for _prefManager.user in order to provide another level of when/return for _prefManager.user.name.
It's like Mockception... you need to go another level deeper in your mocks. ;)

How to verify to call or not to call a method

class MockView extends Mock implements ContactListViewContract {
#override
void onLoadContactsComplete(List<Contact> items) {
}
#override
void onLoadContactsError() {}
}
void main() {
test('ContactListPresenter test', () {
Injector.configure(Flavor.MOCK);
MockView view = new MockView();
ContactListPresenter presenter = new ContactListPresenter(view);
presenter.loadContacts();
verify(view.onLoadContactsComplete).called(1);
});
}
I want to make sure when presenter.loadContacts() is called from the code, then verify view.onLoadContactsComplete is called also but getting an error:
Used on a non-mockito object
Is there a possibility to do this with Mockito?
Update:
abstract class ContactListViewContract {
void onLoadContactsComplete(List<Contact> items);
void onLoadContactsError();
}
here the onLoadContactsComplete method is called
class ContactListPresenter {
ContactListViewContract _view;
ContactRepository _repository;
ContactListPresenter(this._view){
_repository = new Injector().contactRepository;
}
void loadContacts(){
assert(_view != null);
_repository.fetch()
.then((contacts) {
print(contacts);
_view.onLoadContactsComplete(contacts); // here the onLoadContactsComplete method is called
}).catchError((onError) {
print(onError);
_view.onLoadContactsError();
});
}
}
Mocked Repository. Fetch mocked data.
class MockContactRepository implements ContactRepository{
Future<List<Contact>> fetch(){
return new Future.value(kContacts);
}
}
when calling verify method you need call the actual method on the mock
Try
test('ContactListPresenter test', () async {
Injector.configure(Flavor.MOCK);
MockView view = new MockView();
ContactListPresenter presenter = new ContactListPresenter(view);
presenter.loadContacts();
await untilCalled(view.onLoadContactsComplete(typed(any)));
//completes when view.onLoadContactsComplete(any) is called
verify(view.onLoadContactsComplete(typed(any))).called(1);
});
If the method was not called once, the test will fail.
Mockito provides native support for both
To test that your method has been called at least once you can use
verify(<your-method-with-expected-params>) this will verify that your method has called (no matter how many times). To verify that it has been called for a specific number of times you can chain it with .called(<number-of-calls-expected>)
To test that your method hasn't been called you should use verifyNever(<your-method-with-expected-params>) this will validate that your method hasn't been invoked
Make sure that the method passed to both verify and verifyNever are the methods which have been Mocked by Mockito.
You can use never and verifyZeroInteractions
//interaction with mockOne
mockOne.add("one");
//ordinary interaction
verify(mockOne).add("one");
//we never interaction into the mock
verify(mockOne, never()).add("two");
//verify we don't use in the mock
verifyZeroInteractions(mockTwo, mockThree);
*mark verifyZeroInteractions as deprecated in mockito-kotlin, too
introduce an alias for verifyNoInteractions

Jasmine spying on method that calls external method (Angular 2)

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

How do I unit test a non-generic method that calls a generic method in a sealed non-generic class?

using [assembly:InternalsVisibleTo()] and
public sealed class AppService
{
//TODO: fix dev's spelling
//want to test this
public AddSubscribtionResponse AddSubscribtion(AddSubscribtionRequest request)
{
return ExecuteQueryProc<AddSubscribtionResponse>("spAddAppToUserGroup", request).First();
}
//I want to stub or interaction test the call to here
#if DEBUG
internal
#endif
List<T> ExecuteQueryProc<T>(string query, object parameters = null)
{
var cn=GetConnection();
//DatabaseCommand is a static class =(
return DatabaseCommand.ExecuteQueryProc<T>(cn, query, parameters);
}
}
Every attempt I've made at getting Rhino to stub or intercept the Execute Query proc method has failed.
var service = MockRepository.GeneratePartialMock<AppService>(null);
service.Stub(f => f.ExecuteQueryProc<AddSubscribtionRequest>(null, null)).IgnoreArguments().Return(new List<AddSubscribtionRequest>());
var expected = new AddSubscribtionRequest();
var actual = service.AddSubscribtion(expected);
Throws
System.InvalidOperationException: ExecuteReader: CommandText property has not been initialized
Remove the "sealed" from your class (Rhino.Mocks can't proxy your class if it can't inherit from it). And ExecuteQueryProc has to be virtual to be able to stub its functionality.