So I find myself writing this code all the time:
[TestMethod]
[Description("Asserts that an ArgumentNullException is thrown if ResetPassword(null) is called")]
public void ResetPassword_Throws_ArgumentNullException_With_Null_Parameter( )
{
try
{
new MembershipServiceProvider( ).ResetPassword( null );
}
catch ( ArgumentNullException )
{
// ArgumentNullException was expected
Assert.IsTrue( true );
}
catch
{
Assert.Fail( "ArgumentNullException was expected" );
}
}
So instead of writing this code over and over I'd really like to create a method which accepts a Lambda expression which will execute the method in the try block.
Something like this:
public void AssertExpectedException( Action theAction ) where TException : Exception
{
try
{
// Execute the method here
}
catch ( TException )
{
Assert.IsTrue( true );
}
catch
{
Assert.Fail( string.Format( "An exception of type {0} was expected", typeof( TException ) ) );
}
}
So I can do something like this:
var provider = new MembershipServiceProvider();
AssertExpectedException(provider => provider.ResetPassword(null));
I'm really not sure if any of this is on the right track but hopefully someone can point me in the right direction.
Thanks
You're almost there. Here's what the test helper should look like:
public void AssertExpectedException<TException>( Action theAction )
where TException : Exception
{
try
{
// Execute the method here
theAction();
}
catch ( TException )
{
// The Assert here is not necessary
}
catch
{
Assert.Fail( string.Format(
"An exception of type {0} was expected",
typeof(TException)));
}
}
And to call it:
var provider = new MembershipServiceProvider();
AssertExpectedException<ArgumentNullException>(() => provider.ResetPassword(null));
Note the usage of () => something which means the lambda has no parameters. You also have to specify the generic argument of ArgumentNullException because the compiler cannot infer it.
The following should do what you need (I've added the type parameter for TException and the invocation of theAction).
public void AssertExpectedException<TException>(Action theAction)
where TException : Exception
{
try
{
theAction();
}
catch (TException)
{
Assert.IsTrue(true);
}
catch
{
Assert.Fail(string.Format("An exception of type {0} was expected",
typeof(TException)));
}
}
You can call it with the following code:
var provider = new MembershipServiceProvider();
AssertExpectedException<ArgumentNullException>(() => provider.ResetPassword(null));
You need to specify the type argument to indicate which type of exception to test for. The () => ... syntax is a lambda expression that takes no parameters.
Related
this code sample
import 'package:flutter_test/flutter_test.dart';
void main() {
const one = 1;
String oneAsString() => one as String;
test('Make sure it fails', () {
var s;
var _e;
try {
s = oneAsString();
} on Error catch (e) {
_e = e;
}
expect(s == null, true, reason: 'should fail');
expect(_e == null, false, reason: 'error or exception should be returned');
});
test('Catchin Error', () {
var _e;
try {
oneAsString();
} on Error catch (e) {
_e = e;
}
expect(_e is Error, true, reason: 'should be an error');
});
test('Catchin Exception', () {
var _e;
try {
oneAsString();
} on Exception catch (e) {
_e = e;
}
expect(_e is Exception, true, reason: 'should be an exception');
});
test('Why not BOTH', () {
var _e;
try {
oneAsString();
} on Error catch (e) {
_e = e;
} on Exception catch (e) {
_e = e;
}
expect(_e is Error, true, reason: 'should be an error');
expect(_e is Exception, false, reason: 'should NOT be an exception');
});
}
outputs this result
00:02 +2 -1: Catchin Exception [E]
type 'int' is not a subtype of type 'String' in type cast
test/widget_test.dart 5:31 main.oneAsString
test/widget_test.dart 31:18 main.<fn>
00:02 +3 -1: Some tests failed.
the safest approach seems to be Why not BOTH, but following effective dart
(enforcing it with the package effective_dart)
the analysis complains about avoid_catching_errors
DON'T explicitly catch Error or types that implement it.
Errors differ from Exceptions in that Errors can be analyzed and
prevented prior to runtime. It should almost never be necessary to
catch an error at runtime.
BAD:
try { somethingRisky(); } on Error catch(e) { doSomething(e); }
GOOD:
try { somethingRisky(); } on Exception catch(e) { doSomething(e);
}
and if I simple do
try {} catch (e) {}
the analyzer complains about avoid_catches_without_on_clauses
AVOID catches without on clauses.
Using catch clauses without on clauses make your code prone to
encountering unexpected errors that won't be thrown (and thus will go
unnoticed).
BAD:
try { somethingRisky() } catch(e) { doSomething(e); } GOOD:
try { somethingRisky() } on Exception catch(e) { doSomething(e); }
what is the correct approach to catch BOTH Error and Exception?
re-posting the answer from #Miyoyo on r/FlutterDev discord
Optimally? You do not catch error
Just, at all
Remember effective dart is Guidelines
Using them as gospel will make some things impossible
Catching error is deliberately made to be "not according to guidelines"
because you're not supposed to do that
for my use case I'll just add
// ignore_for_file: avoid_catching_errors
Is there a way to abstract this Closure to my MerchantUser model in a way similar to using scopes on with()?
So far I have this which works:
$merchant_user->load(['permissions' => function ($query) use ($merchantId) {
if ($merchantId) {
$query->where('merchant_user_permission.merchant_id','=', $merchantId);
}
}]);
But I'd like to do something like this:
$merchant_user->loadPermissions($merchantId);
In my Model:
public function scopeLoadPermissions($query, $merchantId = null)
{
return $query->load(['permissions' => function ($q) use ($merchantId) {
if ($merchantId) {
$q->where('merchant_user_permission.merchant_id','=', $merchantId);
}
}]);
}
Which at the moment just returns an error:
"Method Illuminate\Database\Query\Builder::load does not exist."
For this case you dont need add scope. Instead if you can add this function in your model
public function loadPermissions($merchantId = null)
{
return $this->load(['permissions' => function ($q) use ($merchantId) {
if ($merchantId) {
$q->where('merchant_user_permission.merchant_id','=', $merchantId);
}
}]);
}
and usage
$merchant_user->loadPermissions($merchantId);
I want to subscribe in company-list.component on getCompanies() from the company.service. However I get the following error:
Cannot read property 'subscribe' of undefined
This is the code:
company.service.ts
getCompaniesOfUser() {
let r;
this.userService.getUser().subscribe(
res=> r = res,
err => console.log(err),
()=>(this.getCompaniesWithSpecificLink())
)
}
getCompaniesWithSpecificLink() {
if (isAdmin == false) {
url = '/user/companies';
} else {
url = '/companies';
}
return this.getCompanies(url);
}
getCompanies(url):Observable<Company[]> {
return this.http.get(this.host + url)
.map((res:Response) => res.json());
}
company-list.component.ts
companies:Company[];
public getTheCompanies() {
this._companyService.getCompaniesOfUser()
.subscribe(companies => this.companies = companies); <-- the error occurred here
}
Subscribe method must be used on an observable but your getCompaniesOfUser() method is not returning anything thus is a void method.
If you want to call back-to-back rest services. Like one's input depending on the others' output. You should use the flatMap operator.
Check this answer for example: https://stackoverflow.com/a/36712707/5706293
Something like this should work:
getCompaniesOfUser() {
return this.userService.getUser().flatMap( (resp) => {
return this.getCompaniesWithSpecificLink();
});
}
Let's say I have the following synchronous code that requires original arguments when handling errors:
var input = createInput(123);
try {
doWork(input);
} catch (err) {
handleError(input, err); // error handling requires input
}
What is the best way to pass the original arguments to the error hander?
Rx.Observable.just(123).map(createInput).map(doWork).subscribe(
function(result) {
// success
},
function(err) {
// how can I get the argument of doWork (the result of createInput) here?
}
);
Just add it as a property of the Error object before you throw it or in wrapper code like below.
...map(function (value) {
try {
return createInput(value);
}
catch (e) {
e.lastValue = value;
throw e;
}
}).subscribe(..., function (e) {
e.lastValue...
There is a parse CloudCode function created as such:
Parse.Cloud.define("getCurrentEvents", function(request, response) {
var TimedEvent = Parse.Object.extend("TimedEvent");
var query = new Parse.Query(TimedEvent);
query.greaterThan("expiresOn", new Date());
query.find({
success: function(results) {
response.success(results);
},
error: function(error) {
response.error("There was an error while looking for TimedEvents");
}
});
});
It returns an array of TimedEvent, as shown in the curl test here:
{"result":[{"expiresOn":{"__type":"Date","iso":"2014-07-31T22:31:00.000Z"},"playMode":"Normal","tableId":"Carnival","objectId":"J1LSO3EnKi","createdAt":"2014-07-28T21:48:22.983Z","updatedAt":"2014-07-28T22:32:14.304Z","__type":"Object","className":"TimedEvent"}]}
When trying to access it from Unity SDK however, I get a "cannot convert to destination type" exception with the following line:
System.Threading.Tasks.Task<Parse.ParseObject[]> task =
Parse.ParseCloud.CallFunctionAsync<Parse.ParseObject[]> ("getCurrentEvents", parameters);
I also tried
System.Threading.Tasks.Task<IEnumerable<Parse.ParseObject>> task =
Parse.ParseCloud.CallFunctionAsync<IEnumerable<Parse.ParseObject[]>> ("getCurrentEvents", parameters);
with the same (lack of) results. What kind of signature is the SDK expecting?
Have you tried something like this (without IEnumerable?):
Threading.Tasks.Task<Parse.ParseObject> task = Parse.ParseCloud.CallFunctionAsync<Parse.ParseObject>("getCurrentEvents", parameters);
But better yet, you could extend ParseObject to create your own TimedEvent class in Unity, like this:
[ParseClassName("TimeEvent")]
public class TimeEvent : ParseObject
{
[ParseFieldName("expiresOn")]
public DateTime expiresOn
{
get { return GetProperty<DateTime>("expiresOn"); }
set { SetProperty(value, "expiresOn"); }
}
[ParseFieldName("playMode")]
public string playMode
{
get { return GetProperty<string>("playMode"); }
set { SetProperty(value, "playMode"); }
}
[ParseFieldName("tableId")]
public string tableId
{
get { return GetProperty<string>("tableId"); }
set { SetProperty(value, "tableId"); }
}
// any other fields you want to access
}
Then you can query your data like this:
IEnumerator getTimedEvents(Dictionary<string, object> parameters)
{
var cloudTask = Parse.ParseCloud.CallFunctionAsync<TimeEvent>("getCurrentEvents", parameters);
while (!cloudTask.IsCompleted)
yield return null;
if (cloudTask.IsCanceled || cloudTask.IsFaulted)
{
// handle error
}
else
{
TimeEvent t = cloudTask.Result;
// do stuff with t
}
}
P.S. Don't forget to register your Parse class somewhere (I usually do it in the Awake() of an early GameObject). In your case, you would do it like this:
Parse.ParseObject.RegisterSubclass<TimedEvent>();