Полный гайд по тестированию на Flutter. Часть 3: Mocking и Stubbing

(Написание Unit-тестов для методов класса)

import 'package:shared_preferences/shared_preferences.dart';


class LoginViewModel {

bool login(String email, String password) {

return Validator.validateEmail(email) && Validator.validatePassword(password);

}

}

group('login', () {

test('login should return false when the email and password are invalid', () {

final loginViewModel = LoginViewModel();

final result = loginViewModel.login('', '');

expect(result, false);

});


test('login should return true when the email and password are valid', () {

final loginViewModel = LoginViewModel();

final result = loginViewModel.login('ntminh@gmail.com', 'password123');

expect(result, true);

});

});

import 'package:flutter/foundation.dart';

import 'package:shared_preferences/shared_preferences.dart';


class LoginViewModel {

final SharedPreferences sharedPreferences;


LoginViewModel({

required this.sharedPreferences,

});


bool login(String email, String password) {

final storedPassword = sharedPreferences.getString(email);


return password == storedPassword;

}


Future<bool> logout() async {

bool success = false;

try {

success = await sharedPreferences.clear();

} catch (e) {

success = false;

}


if (!success) {

throw FlutterError('Logout failed');

}


return success;

}

}

(Mocking и Stubbing)

dev_dependencies:

mocktail: 1.0.3

class MockSharedPreferences extends Mock implements SharedPreferences {}

final mockSharedPreferences = MockSharedPreferences();

// Stubbing

when(() => mockSharedPreferences.getString(email)).thenReturn('123456');

test('login should return false when the password are incorrect', () {

// Arrange

final mockSharedPreferences = MockSharedPreferences(); // create mock object

final loginViewModel = LoginViewModel(sharedPreferences: mockSharedPreferences);

String email = 'ntminh@gmail.com';

String password = 'abc'; // incorrect password


// Stubbing

when(() => mockSharedPreferences.getString(email)).thenReturn('123456');


// Act

final result = loginViewModel.login(email, password);


// Assert

expect(result, false);

});

test('login should return false when the password are correct', () {

// Arrange

final mockSharedPreferences = MockSharedPreferences(); // create mock object

final loginViewModel = LoginViewModel(sharedPreferences: mockSharedPreferences);

String email = 'ntminh@gmail.com';

String password = '123456'; // correct password


// Stubbing

when(() => mockSharedPreferences.getString(email)).thenReturn('123456');


// Act

final result = loginViewModel.login(email, password);


// Assert

expect(result, true);

});

when(() => mockSharedPreferences.clear()).thenAnswer((_) => Future.value(true));

when(() => mockSharedPreferences.clear()).thenThrow(Exception('Clear failed'));

group('logout', () {

test('logout should return true when the clear method returns true', () async {

// Arrange

final mockSharedPreferences = MockSharedPreferences();

final loginViewModel = LoginViewModel(sharedPreferences: mockSharedPreferences);


// Stubbing

when(() => mockSharedPreferences.clear()).thenAnswer((_) => Future.value(true));


// Act

final result = await loginViewModel.logout();


// Assert

expect(result, true);

});


test('logout should throw an exception when the clear method returns false', () async {

// Arrange

final mockSharedPreferences = MockSharedPreferences();

final loginViewModel = LoginViewModel(sharedPreferences: mockSharedPreferences);


// Stubbing

when(() => mockSharedPreferences.clear()).thenAnswer((_) => Future.value(false));


// Act

final call = loginViewModel.logout;


// Assert

expect(call, throwsFlutterError);

});


test('logout should throw an exception when the clear method throws an exception', () async {

// Arrange

final mockSharedPreferences = MockSharedPreferences();

final loginViewModel = LoginViewModel(sharedPreferences: mockSharedPreferences);


// Stubbing

when(() => mockSharedPreferences.clear()).thenThrow(Exception('Logout failed'));


// Act

final Future<bool> Function() call = loginViewModel.logout;


// Assert

expect(

call,

throwsA(isA<FlutterError>().having((e) => e.message, 'error message', 'Logout failed')),

);

});

});

final Future<bool> Function() call = loginViewModel.logout;

expect(

call,

throwsA(isA<FlutterError>().having((e) => e.message, 'error message', 'Logout failed')),

);

(Заключение)

Хотите связаться с владельцем
компании напрямую?
Дмитрий Тарасов
Дмитрий Тарасов
СЕО

НАПИСАТЬ