how to test that the function under test has thrown an exception - scalatest

In my scala and play code, a function throws an exception
case None => {
println("error in updating password info")
throw new Exception("error in updating password info") //TODOM - refine errors. Make errors well defined. Pick from config/env file
}
I want to test the above code but I don't know how to test that the Exception was thrown. The spec I have written is
"PasswordRepository Specs" should {
"should not add password for non-existing user" in {
val newPassword = PasswordInfo("newHasher","newPassword",Some("newSalt"))
when(repoTestEnv.mockUserRepository.findOne(ArgumentMatchers.any())).thenReturn(Future{None}) //THIS WILL CAUSE EXCEPTION CODE TO GET EXECUTED
val passwordRepository = new PasswordRepository(repoTestEnv.testEnv.mockHelperMethods,repoTestEnv.mockUserRepository)
println(s"adding password ${newPassword}")
val passwordInfo:PasswordInfo = await[PasswordInfo](passwordRepository.add(repoTestEnv.testEnv.loginInfo,newPassword))(Timeout(Duration(5000,"millis"))) //add SHOULD THROW AN EXCEPTION BUT HOW DO I TEST IT???
}
}

Thanks JB Nizet. I must confess I was being lazy! The correct way is either to use assertThrow or interrupt. Eg.
val exception:scalatest.Assertion = assertThrows[java.lang.Exception](await[PasswordInfo(passwordRepository.add(repoTestEnv.testEnv.loginInfo,newPassword)
)(Timeout(Duration(5000,"millis"))))
or
val exception = intercept[java.lang.Exception](await[Unit](passwordRepository.remove(repoTestEnv.testEnv.loginInfo))(Timeout(Duration(5000,"millis"))))
println(s"exception is ${exception}")
exception.getMessage() mustBe repoTestEnv.testEnv.messagesApi("error.passwordDeleteError")(repoTestEnv.testEnv.langs.availables(0))

Related

Flutter - Why do I get 'Unhandled Exception: Concurrent modification during iteration' from a database query?

I'm having some trouble understanding an issue regarding flutters database handling (at least I assume so since that's where the issue seems to be). When I run my app I get the following error message:
E/flutter (26185): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Concurrent modification during iteration: Instance(length:13) of '_GrowableList'.
E/flutter (26185): #0 ListIterator.moveNext (dart:_internal/iterable.dart:336:7)
E/flutter (26185): #1 _MyHomePageState._processBle.<anonymous closure> (package:blescanner/screens/home_view.dart:283:27)
E/flutter (26185): <asynchronous suspension>
I've put a lot of effort trying to find why this is. The row 283 referenced is my "for (var element in list){"-row in MyHomePage, but to my knowledge I'm not trying to modify that list anywhere. After some time I just started commenting away line after line to find what the cause of the issue and it turns out that it disappeared when I commented away the "dbHelper.getBlItemLog"-call. That led me into that function (code included further down) where the issue seems to be the database query. I thought that it might be some issue with the database being modified during the query, so I removed all other calls to the database, but the issue remained. How can a database query cause this kind of issue? I just can't understand why? does anyone have any kind of insight or suggestion regarding this?
from MyHomePage (which extends Stateful Widget):
void _processBle() {
FlutterBluePlus.instance.scanResults.forEach((list) async {
for (var element in list) {
String bleName = element.device.name;
dev.log('Found device: ' + bleName);
String blItemId = bleName.replaceAll('XXX', '');
var blItemData = CustomBluetoothItem.fromBle(bleName,
blItemId,
element.advertisementData.manufacturerData,
_geoPos.lat, _geoPos.long
);
int tempStatus = blItemData.status;
try {
if (blItemData.status > 1) {
await lock.synchronized(() async {
dev.log('${DateTime.now()
.toIso8601String()} _processBle .. start $bleName');
//here's where I call the troubling function
await dbHelper.getBlItemLog(
bleName: bleName, startDate: blItemData.sDate)
.then((queueItem) async {
// the stuff in here is commented away for now and thus doesn't matter
});
dev.log('${DateTime.now()
.toIso8601String()} _processBle .. stop ${element.device
.name}');
});
}
} catch (e) {
dev.log('error : $e');
}
}
});
firstStartup = false;
dev.log('_processBle - ### done');
}
from my dbHelper:
Future<CustomBluetoothItem?> getBlItemLog({required String bleName, required String startDate}) async {
Database? db = await database;
//the following line seems to be where the issue is, since there's no issue if I comment it away.
List<Map<String, dynamic>> maps = await db!.rawQuery('SELECT * FROM ble_table WHERE bleName = ? AND startDate = ? ORDER BY createDate desc limit 1 offset 0',[bleName,startDate]);
if (maps.isNotEmpty) {
return CustomBluetoothItem.fromJson(maps[0]);
}
return null;
}

how do you detect createUpdate() fails?

public Connection executeUpdate() {
long start = System.currentTimeMillis();
try {
this.logExecution();
PreparedStatement statement = this.buildPreparedStatement();
this.connection.setResult(statement.executeUpdate());
this.connection.setKeys(this.returnGeneratedKeys ? statement.getGeneratedKeys() : null);
this.connection.setCanGetKeys(this.returnGeneratedKeys);
} catch (SQLException var7) {
this.connection.onException();
throw new Sql2oException("Error in executeUpdate, " + var7.getMessage(), var7);
} finally {
this.closeConnectionIfNecessary();
}
long end = System.currentTimeMillis();
logger.debug("total: {} ms; executed update [{}]", new Object[]{end - start, this.getName() == null ? "No name" : this.getName()});
return this.connection;
}
I'm wondering how to test an update failing. The query I'm using is:
update my_table set some_field=:some_value
where the_key = :the_key_value
And, immediately before executeUpdate() runs, I am deleting the record where the_key == "the_key_value".
Does anyone know the correct way to determine if the update failed?
Also, when I go to the javadoc and click on anything, I get:
CDN object Not Found - Request ID: c6a9ba5f-f8ea-46ae-bf7a-efc084971878-19055563
Is there a way to build javadoc locally?
EDIT: is the way to check this thru the use of Connection.getResult()? Does it return the number of records updated/inserted etc?
I went and RTFM which explained how to do this.

Gatling2 Failing to use user session properly

I hope someone can point me into the right direction!
I try to run one scenario which has several steps that have to be executed in order and each with the same user session to work properly. The below code works fine with one user but fails if I use 2 or more users...
What am I doing wrong?
val headers = Map(
Constants.TENANT_HEADER -> tenant
)
val httpConf = http
.baseURL(baseUrl)
.headers(headers)
val scen = scenario("Default Order Process Perf Test")
.exec(OAuth.getOAuthToken(clientId))
.exec(session => OAuth.createAuthHHeader(session, clientId))
.exec(RegisterCustomer.registerCustomer(customerMail, customerPassword,
tenant))
.exec(SSO.doLogin(clientId, customerMail, customerPassword, tenant))
.exec(session => OAuth.upDateAuthToken(session, clientId))
.exec(session =>
UpdateCustomerBillingAddr.prepareBillingAddrRequestBody(session))
.exec(UpdateCustomerBillingAddr.updateCustomerBillingAddr(tenant))
.exec(RegisterSepa.startRegisterProcess(tenant))
.exec(session => RegisterSepa.prepareRegisterRequestBody(session))
.exec(RegisterSepa.doRegisterSepa(tenant))
setUp(
scen
.inject(atOnceUsers(2))
.protocols(httpConf))
object OAuth {
private val OBJECT_MAPPER = new ObjectMapper()
def getOAuthToken(clientId: String) = {
val authCode = PropertyUtil.getAuthCode
val encryptedAuthCode = new
Crypto().rsaServerKeyEncrypt(authCode)
http("oauthTokenRequest")
.post("/oauth/token")
.formParam("refresh_token", "")
.formParam("code", encryptedAuthCode)
.formParam("grant_type", "authorization_code")
.formParam("client_id", clientId)
.check(jsonPath("$").saveAs("oauthToken"))
.check(status.is(200))
}
def createAuthHHeader(session: Session, clientId: String) = {
val tokenString = session.get("oauthToken").as[String]
val tokenDto = OBJECT_MAPPER.readValue(tokenString,
classOf[TokenDto])
val session2 = session.set(Constants.TOKEN_DTO_KEY, tokenDto)
val authHeader = AuthCommons.createAuthHeader(tokenDto,
clientId, new util.HashMap[String, String]())
session2.set(Constants.AUTH_HEADER_KEY, authHeader)
}
def upDateAuthToken(session: Session, clientId: String) = {
val ssoToken = session.get(Constants.SSO_TOKEN_KEY).as[String]
val oAuthDto = session.get(Constants.TOKEN_DTO_KEY).as[TokenDto]
val params = new util.HashMap[String, String]
params.put("sso_token", ssoToken)
val updatedAuthHeader = AuthCommons.createAuthHeader(oAuthDto,
clientId, params)
session.set(Constants.AUTH_HEADER_KEY, updatedAuthHeader)
}
}
def createAuthHHeader(session: Session, clientId: String) = {
val tokenString = session.get("oauthToken").as[String]
val tokenDto = OBJECT_MAPPER.readValue(tokenString,
classOf[TokenDto])
val session2 = session.set(Constants.TOKEN_DTO_KEY, tokenDto)
val authHeader = AuthCommons.createAuthHeader(tokenDto,
clientId, new util.HashMap[String, String]())
session2.set(Constants.AUTH_HEADER_KEY, authHeader)
}
So I did add the two methods that dont work along as expected. In the first part I try to fetch a token and store in the session via check(jsonPath("$").saveAs("oauthToken")) and in the second call I try to read that token with val tokenString = session.get("oauthToken").as[String] which fails with the exception saying that there is no entry for that key in the session...
I've copied it and removed/mocked any missing code references, switched to one of my apps auth url and it seems to work - at least 2 firsts steps.
One thing that seems weird is jsonPath("$").saveAs("oauthToken") which saves whole json (not single field) as attribute, is it really what you want to do? And are you sure that getOAuthToken is working properly?
You said that it works for 1 user but fails for 2. Aren't there any more errors? For debug I suggest changing logging level to TRACE or add exec(session => {println(session); session}) before second step to verify if token is properly saved to session. I think that something is wrong with authorization request (or building that request) and somehow it fails or throws some exception. I would comment out all steps except 1st and focus on checking if that first request is properly executed and if it adds proper attribute to session.
I think your brackets are not set correctly. Change them to this:
setUp(
scn.inject(atOnceUsers(2))
).protocols(httpConf)

Can't update Boolean value in Apex

I cannot update update this Boolean value in Apex. What is going wrong? The if statement, and the fact that the front end representation is a checkbox, proves that it is indeed a boolean value. I am new to Apex so I feel its a basic misunderstanding of how it works. Can anyone help me out?
Here is the code that I'm executing in an Anonymous Window.
Account acc = new Account(Name='Test Name');
if (acc.Do_Not_Contact__pc == false) {
System.debug('DNC is false');
} else {
System.debug('DNC is true');
}
insert acc;
acc.Do_Not_Contact__pc = true;
update acc;
It fails on the second to last line, displaying the following message:
System.DmlException: Update failed. First exception on row 0 with id 001W000000fFiVbIAK; first error: INVALID_FIELD_FOR_INSERT_UPDATE, Account: bad field names on insert/update call: Do_Not_Contact__pc: [Do_Not_Contact__pc]
What's particularly frustrating is that when I change the second to last line to
acc.Do_Not_Contact__pc = 'true';
I get an error stating that I cannot assign a String to a Boolean value
Remove the single quotes and I assume you typed the field name wrong. Try acc.Do_Not_Contact__c = true;

C# login message warning

Well im here because i have a problem. i have code that was created a while ago. my code is working properly when i a user type the correct username and password. so my problem is when a user insert wrong username and password error message wont show. Here is my code:
MyDs.Clear();
MyDa.SelectCommand = Conn.CreateCommand();
MyDa.SelectCommand.CommandText =
"select * from PersonalName where Firstname=#first and Lastname=#last";
MyDa.SelectCommand.CommandType = CommandType.Text;
MyDa.SelectCommand.Parameters.Add("#first", DbType.String, 25, "Firstname").Value = textbox_Username.Text;
MyDa.SelectCommand.Parameters.Add("#last", DbType.String, 25, "Lastname").Value = textbox_Password.Text;
MyDa.Fill(MyDs);
foreach (DataRow item in MyDs.Tables[0].Rows)
{
if (textbox_Username.Text != item[1].ToString() || textbox_Password.Text != item[3].ToString())
{
MessageBox.Show("not connected");
}
else
{
MessageBox.Show("Connected");
}
}
Anyone can tell me what is the problem with this code?
Your dataset will be empty if they put in the wrong username. This will be closer to what you want:
if (MyDs.Tables[0].Rows.Count > 0)
{
// you don't need to check username, the SQL query took care of that
if (textbox_Password.Text == item[3].ToString())
MessageBox.Show("Connected.");
else
MessageBox.Show("Failed."); // wrong password
}
else
MessageBox.Show("Failed."); // no such user
if the query returns no records becasue firast and last name aren't present, foreach doesn't execute nothing happens...
You need to test for myDa being empty as well, your code only works for checking valid users.

Resources