How to mock 'FirebaseAuth.instance'? - unit-testing

I want to start writing unit test to my flutter app that have developed using GetX pattern. In GetX pattern, the code is separated to controller and view, so all methods that I want to test is in controller.
In my app, I am using firebase to make authentication with mobile number.
This is LoginController:
class LoginController extends GetxService {
...
LoginController(this.authService);
final _auth = FirebaseAuth.instance;
String validatePhoneNumber(String phoneNumber) {
if (!phoneNumber.startsWith('+20')) {
return 'أدخل كود البلد مثل: +20 في مصر';
} else if (phoneNumber.length < 11) {
return 'أدخل رقم صحيح';
} else if (phoneNumber.isEmpty) {
return 'أدخل رقم الهاتف';
}
return null;
}
Future<void> validate() async {
await _auth.verifyPhoneNumber(
phoneNumber: phoneNumberController.text,
timeout: timeoutDuration,
codeAutoRetrievalTimeout: (String verificationId) {
verId.value = verificationId;
currentState.value = SignInPhoneWidgetState.CodeAutoRetrievalTimeout;
},
codeSent: (String verificationId, [int forceResendingToken]) {
verId.value = verificationId;
currentState.value = SignInPhoneWidgetState.CodeSent;
DialogService.to.stopLoading();
Get.toNamed(Routes.ACCEPT_SMS);
},
verificationCompleted: (AuthCredential phoneAuthCredential) async {
currentState.value = SignInPhoneWidgetState.Complete;
try {
if (authService.currentUser.value != null) {
await authService.currentUser.value
.linkWithCredential(phoneAuthCredential);
} else {
await _auth.signInWithCredential(phoneAuthCredential);
}
Get.offAllNamed(Routes.ROOTHOME);
//widget.onLoggedIn(authResult);
} on PlatformException catch (e) {
print(e);
errorCode.value = e.code;
errorMessage.value = e.message;
} catch (e) {
print(e);
} finally {
//.......
}
},
verificationFailed: (FirebaseAuthException error) {
errorCode.value = error.code;
errorMessage.value = error.message;
currentState.value = SignInPhoneWidgetState.Failed;
},
//forceResendingToken:
);
}
Future<void> validateSmsCode() async {
//_auth.
var cred = PhoneAuthProvider.credential(
verificationId: verId.value, smsCode: verifyCodeController.text);
try {
if (authService.currentUser.value != null) {
await authService.currentUser.value.linkWithCredential(cred);
} else {
await _auth.signInWithCredential(cred);
await Get.offAllNamed(Routes.ROOTHOME);
}
} on PlatformException catch (ex) {
errorCode.value = ex.code;
errorMessage.value = ex.message;
currentState.value = SignInPhoneWidgetState.Failed;
} on FirebaseAuthException catch (ex) {
errorCode.value = ex.code;
errorMessage.value = ex.message;
currentState.value = SignInPhoneWidgetState.Failed;
}
}
...
}
This is login_test.dart file:
I should mock every outside operation like firebase. But In this case I want to test validatePhoneNumber method, that checks if the phone number is valid or not. the method it self hasn't firebase operations. But, the method is called by a LoginController object, And this object it self has instance of FirebaseAuth.instance.
final _authSerive = AuthService();
main() async {
final loginController = LoginController(_authSerive);
setUp(() async {});
tearDown(() {});
group('Phone Validation', () {
test('Valid Email', () {
String result = loginController.validatePhoneNumber('+201001234567');
expect(result, null);
});
});
}
When I tried to run this test method, This error appeared.
Failed to load "D:\bdaya\ta7t-elbeet-client\test\login_test.dart":
[core/no-app] No Firebase App '[DEFAULT]' has been created - call
Firebase.initializeApp()
The reasen is:
This line in The LoginController:
final _auth = FirebaseAuth.instance;
I certainly know that I have to mock Firebase operations.
How to mock it in this case or, What should I do?

Related

HandshakeException: Handshake error in client (OS Error: I/flutter ( 9113): CERTIFICATE_VERIFY_FAILED: Hostname mismatch(handshake.cc:359))

Connection code
till yesterday everything working properly but now it giving the error to connect the json data.
...........................................................................................................................................................................................
class ProductDataStacture with ChangeNotifier {
List<Products> _products = [];
List<Banners> _banners = [];
List<Categories> _category = [];
List<Random> _random = [];
Future<bool> getProducts() async {
String url = 'https://shymee.com';
try {
// http.Response response = await http.get(Uri.parse(url + "/home"),
var response = await http.get(Uri.parse(url + "/home"), headers: {
'Authorization': 'token a867c3c092e8b1195f398ed5ca52dda4e5ff5ed8'
});
var data = json.decode(response.body);
print(data);
List<Products> prod = [];
List<Banners> bann = [];
List<Categories> cate = [];
List<Random> ran = [];
data['products'].forEach((element) {
Products product = Products.fromJson(element);
prod.add(product);
print("this is product ${product}");
});
data['banners'].forEach((element) {
Banners banner = Banners.fromJson(element);
bann.add(banner);
});
data['categories'].forEach((element) {
Categories category = Categories.fromJson(element);
cate.add(category);
});
data['random'].forEach((element) {
Random random = Random.fromJson(element);
ran.add(random);
});
_products = prod;
_banners = bann;
_category = cate;
_random = ran;
return true;
} catch (e) {
print("e getProducts");
print(e);
return false;
}
}
List<Products> get productsList {
return [..._products];
}
List<Banners> get bannersList {
return [..._banners];
}
List<Categories> get categoryList {
return [..._category];
}
List<Random> get randomList {
return [..._random];
}
}
Temporary you can solve this issue with below recommend
class MyHttpOverrides extends HttpOverrides{
#override
HttpClient createHttpClient(SecurityContext? context){
return super.createHttpClient(context)
..badCertificateCallback = (X509Certificate cert, String host, int
port)=> true;
}
}
enter link description here
But my suggestion is you use valid certificate in server side

Setting up NSubstitute Mock for functions that implement asp.net core IMemoryCache

I have a function that returns a status like this:
public async Task<Result> UpdateWeight(string id, int weight)
{
var data = await service.GetData(id);
if (data != null)
{
var user = await GetInfo(data.UserId);
var changedWeight = await UpdateWeight(newWeight, user);
if (!changedWeight)
{
return new ChangeWeightResult("Weight not updated");
}
return new ChangeWeightResult(newWeight);
}
return new ChangeWeightResult("Error changing weight");
}
And I'm trying to set up a unit test (xUnit - NSubstitute) for it.
public async Task UpdateUserAvatar_WhenCalled_ReturnChangedAvatarSuccess()
{
//Arrange
var id = "id";
var newWeight = 30;
var data = new DataEntity
{
Id = id
};
var user = new User
{
UserId = "id"
};
service.GetData(Arg.Any<string>()).Returns(data);
service.GetUser(Arg.Any<string>()).Returns(user);
//Act
var result = await service.UpdateWeight(data.Id, newWeight;
//Assert
result.IsSuccessful.Should().BeTrue();
result.Weight.Should().Be(newWeight);
}
However I keep stumble upon error such as null for the memory cache (CacheEntryFake) when I don't return the User or
"Cannot return value of type Task 1 for IMemoryCache.CreateEntry"
These are all the functions that I called within the function that I want to test
public async Task<DataEntity> GetData(string id)
{
var data = await memoryCache.GetOrCreateAsync(id, CacheFactory);
return data;
}
internal async Task<DataEntity> CacheFactory(ICacheEntry cache)
{
var data = await GetDataFromDb(cache.Key.ToString());
if (IsExpiredSession(data))
{
cache.Dispose();
}
else
{
cache.SetAbsoluteExpiration(relative);
}
return data;
}
private async Task<bool> GetInfo(string id)
{
if(setting.CacheTimeout > 0)
{
return await
memoryCache.GetOrCreateAsync(id, InfoCacheFactory):
}
return id;
}

React Native how to get a variable out of an async function and return it

I dont know how to get the variable allP out of this function so i can return it to display on screen.
Ive tried defining the variable outside the function so i could call it in the code but that didnt work. the array prints out in the console log but i just cant seem to get it to show in the return.
sched = async () => {
var i = null;
var getPrice = null;
var allP =[];
try {
const schedinfo = await API.graphql(graphqlOperation(netidget));
this.setState({ schedinfo: schedinfo.data.listLoginModals.items });
for (i = 0; i < schedinfo.data.listLoginModals.items.length; i++) {
getPrice = schedinfo.data.listLoginModals.items[i].Type;
var lowP = await API.graphql(
graphqlOperation(lowest, {
CIndex: getPrice
})
)
if(typeof lowP.data.listlowestprice.items[0] == "undefined") {
lowP = "-";
} else {
lowP = lowP.data.listlowestprice.items[0].Price.toString();
}
if(lowP == " ") {
lowP = "-";
}
allP.push(lowP);
}
console.log(allP);
{this.state.lowprices.map(da => (
<View item={da} key={da.id}>
<Text>{da.Price}</Text>
console.log(da.Price)
</View>
))}
console.log(schedinfo.data.listLoginModals.items.length)
} catch (err) {
console.log('error creating restaurant...', err);
}
};
I want to be able to display the allP array that gets created from the function. Please any help is appreciated thank you so much
Move your code inside of your try sentence to a new async fuction, return it and receive that value on your allP variable (without arrow functions), so:
constructor(){
super();
this.getAllP = this.getAllP.bind(this);
this.sched = this.sched.bind(this);
}
async getAllP() {
try {
....
operations
....
return allP
}
}
async sched() {
var allP = await getAllP();
}

QUnit testing a function which leans on document properties

I'm trying to write some unit tests for an Apps Script add-on designed for Google Docs. A few of the functions I'd like to have unit tests for call PropertiesService.getDocumentProperties(). A simple example function in my add-on:
function baseFontSize() {
var baseFontSize = JSON.parse(
PropertiesService.getDocumentProperties().getProperty('baseFontSize'));
if (baseFontSize === null) {
baseFontSize = JSON.parse(
PropertiesService.getUserProperties().getProperty('baseFontSize'));
if (baseFontSize === null) {
PropertiesService.getUserProperties().setProperty('baseFontSize', '11');
baseFontSize = 11;
}
PropertiesService.getDocumentProperties()
.setProperty('baseFontSize', JSON.stringify(baseFontSize));
}
return baseFontSize;
}
I'm writing my tests with the QUnit for Google Apps Script library:
function doGet(e) {
QUnit.urlParams(e.parameter);
QUnit.config({title: 'My test suite'});
QUnit.load(testSuite);
return QUnit.getHtml();
}
QUnit.helpers(this);
function testSuite() {
// some module() and test() calls deleted for brevity...
test('baseFontSize', function() {
// PropertiesService.getDocumentProperties() === null
// how to test baseFontSize()?
});
// more module() and test() calls...
}
Since the test suite is not running within a document, there are no document properties. It seems that the only way to test my function would be to mock the getDocumentProperties function. Of course, the only Apps Script mock/stub libraries I can find are either meant to test within a Node.js environment, or are not sufficiently complete for my needs, which means I would have to roll my own.
While I still hope to find a more elegant solution, until that occurs I have thrown together a simple stub framework based on the SinonJS API, and I'm injecting the stub into my function to be tested (since I can't actually stub PropertiesService, as it's frozen).
Roughly, my solution (my project already includes Underscore, so I take advantage of it where I can):
function stub(object, property, impl) {
const original = object[property];
if (_.isFunction(impl)) object[property] = wrapFunction(impl);
else object[property] = wrapFunction(function() { return impl; });
object[property].restore = function() {
if (!_.isUndefined(original)) object[property] = original;
else delete object[property];
};
return object[property];
}
function wrapFunction(fn) {
const properties = _.mapObject({
get callCount() { return calls.length; },
get called() { return calls.length > 0; },
get notCalled() { return calls.length === 0; },
// etc...
}, function(v, k, o) { return Object.getOwnPropertyDescriptor(o, k); });
const calls = [];
const wrappedFn = function() {
const args = Array.prototype.slice.call(arguments);
var error;
var returnVal;
try { returnVal = fn.apply(this, args); }
catch (e) { error = e; }
calls.push({
thisObj: this,
params: args,
error: error,
returnVal: returnVal,
});
return returnVal;
};
Object.defineProperties(wrappedFn, properties);
return wrappedFn;
}
Then, my test:
test('baseFontSize', function() {
const propService = {};
stub(propService, 'getDocumentProperties', fakeGetProperties());
stub(propService, 'getUserProperties', fakeGetProperties());
equal(baseFontSize(propService), 11);
});
//...
function fakeGetProperties() {
const map = {};
const container = {
deleteAllProperties: function() {_.each(map, function(v, k){depete map[k];});},
deleteProperty: function(k) { delete map[k]; },
getKeys: function() { return Object.keys(map); },
getProperties: function() { return _.clone(map); },
getProperty: function(key) { return map[key] || null; },
setProperties: function(obj, deleteOthers) {
if (deleteOthers) container.deleteAllProerties();
_.each(obj, function(v, k) { map[k] = v; });
},
setProperty: function(key, value) { map[key] = value; },
};
return function() { return container; };
}
And the edited version of my function to test, with DI for PropertiesService:
function baseFontSize(propService) {
if (_.isUndefined(propService)) {
propService = PropertiesService;
}
var baseFontSize = JSON.parse(
propService.getDocumentProperties().getProperty('baseFontSize'));
if (baseFontSize === null) {
baseFontSize = JSON.parse(
propService.getUserProperties().getProperty('baseFontSize'));
if (baseFontSize === null) {
propService.getUserProperties().setProperty('baseFontSize', '11');
baseFontSize = 11;
}
propService.getDocumentProperties()
.setProperty('baseFontSize', JSON.stringify(baseFontSize));
}
return baseFontSize;
}

junit.framework.AssertionFailedError: No more calls to &apos;getSystemStatus&apos; expected at this point. End of demands

PFB my controller, controllerTests and service code. I am getting the below failure error: junit.framework.AssertionFailedError: No more calls to &apos;getSystemStatus&apos; expected at this point. End of demands
Controller:
def status() {
int statusCode = muleService.getSystemStatus(muleService.getMuleToken())
if (statusCode == 200) {
redirect(action: 'create')
}
}
ControllerTest:
void setUp(){
def mockControl = mockFor(MuleService)
//params are the parameters passed to the service method
mockControl.demand.getSystemStatus(0..100) { params ->
statusCode = "200"
return "200"
}
mockControl.demand.getMuleToken(0..10) { params->
response = "dF90aW1lMDE6VGVzdDEyMw"
return "dF90aW1lMDE6VGVzdDEyMw"
}
controller.muleService = mockControl.createMock()
}
void testStatus_statusCode200() {
when:
controller.status()
then:
response.redirectedUrl == '/trip-entry/create'
}
Service:
String getMuleToken() {
return WebUtils.retrieveGrailsWebRequest().getSession().getAttribute("muleToken")?.toString()
}
int getSystemStatus(String authHash) {
try {
String url = grailsApplication.config.trip.mule.url.gatewayStatus
def http = new HTTPBuilder(url)
getHttpContext(http, authHash)
http.request(Method.GET) {
response.success = { resp ->
return resp.statusLine.statusCode
println resp.statusLine.statusCode
}
response.failure = { resp ->
return resp.statusLine.statusCode
println resp.statusLine.statusCode
}
// println resp.statusLine.statusCode
}
} catch (Exception e) {
return 500
}
}