In my 'act' I want to capture an exception so that I can do multiple tests on the exception data. Examples on the web show how to capture and compare the type/message within a test (or 'It' block) but not how to capture the exception as an 'act' in itself.
I am currently just doing a try/catch within the 'act' body and storing the exception within the context for later testing in the 'It' block. There I can perform a number of different fluent assertions on the data. Is this the best approach?
Actually, there is indeed a better way to do this:
void describe_some_exceptional_behavior()
{
context["when throwing an exception"] = () =>
{
act = () => throw new InvalidOperationException();
it["should raise the exception"] = expect<InvalidOperationException>();
};
}
Note: you assign the result of expect directly to it. This tripped me up the first time.
See the nspec specs for more examples.
I don't think there currently is another way to achieve that apart from manual try catch blocks for storing the exception and later checking on it in an it block.
If you're willing to use an open-source framework, you could use Fluent Assertions and do this:
Action act = () => subject.Foo2("Hello");
act.ShouldThrow()
.WithInnerException()
.WithInnerMessage("whatever");
Related
I have tried to unsubscribe within the subscribe method. It seems like it works, I haven't found an example on the internet that you can do it this way.
I know that there are many other possibilities to unsubscribe the method or to limit it with pipes. Please do not suggest any other solution, but answer why you shouldn't do that or is it a possible way ?
example:
let localSubscription = someObservable.subscribe(result => {
this.result = result;
if (localSubscription && someStatement) {
localSubscription.unsubscribe();
}
});
The problem
Sometimes the pattern you used above will work and sometimes it won't. Here are two examples, you can try to run them yourself. One will throw an error and the other will not.
const subscription = of(1,2,3,4,5).pipe(
tap(console.log)
).subscribe(v => {
if(v === 4) subscription.unsubscribe();
});
The output:
1
2
3
4
Error: Cannot access 'subscription' before initialization
Something similar:
const subscription = of(1,2,3,4,5).pipe(
tap(console.log),
delay(0)
).subscribe(v => {
if (v === 4) subscription.unsubscribe();
});
The output:
1
2
3
4
This time you don't get an error, but you also unsubscribed before the 5 was emitted from the source observable of(1,2,3,4,5)
Hidden Constraints
If you're familiar with Schedulers in RxJS, you might immediately be able to spot the extra hidden information that allows one example to work while the other doesn't.
delay (Even a delay of 0 milliseconds) returns an Observable that uses an asynchronous scheduler. This means, in effect, that the current block of code will finish execution before the delayed observable has a chance to emit.
This guarantees that in a single-threaded environment (like the Javascript runtime found in browsers currently) your subscription has been initialized.
The Solutions
1. Keep a fragile codebase
One possible solution is to just ignore common wisdom and continue to use this pattern for unsubscribing. To do so, you and anyone on your team that might use your code for reference or might someday need to maintain your code must take on the extra cognitive load of remembering which observable use the correct scheduler.
Changing how an observable transforms data in one part of your application may cause unexpected errors in every part of the application that relies on this data being supplied by an asynchronous scheduler.
For example: code that runs fine when querying a server may break when synchronously returned a cashed result. What seems like an optimization, now wreaks havoc in your codebase. When this sort of error appears, the source can be rather difficult to track down.
Finally, if ever browsers (or you're running code in Node.js) start to support multi-threaded environments, your code will either have to make do without that enhancement or be re-written.
2. Making "unsubscribe inside subscription callback" a safe pattern
Idiomatic RxJS code tries to be schedular agnostic wherever possible.
Here is how you might use the pattern above without worrying about which scheduler an observable is using. This is effectively scheduler agnostic, though it likely complicates a rather simple task much more than it needs to.
const stream = publish()(of(1,2,3,4,5));
const subscription = stream.pipe(
tap(console.log)
).subscribe(x => {
if(x === 4) subscription.unsubscribe();
});
stream.connect();
This lets you use a "unsubscribe inside a subscription" pattern safely. This will always work regardless of the scheduler and would continue to work if (for example) you put your code in a multi-threaded environment (The delay example above may break, but this will not).
3. RxJS Operators
The best solutions will be those that use operators that handle subscription/unsubscription on your behalf. They require no extra cognitive load in the best circumstances and manage to contain/manage errors relatively well (less spooky action at a distance) in the more exotic circumstances.
Most higher-order operators do this (concat, merge, concatMap, switchMap, mergeMap, ect). Other operators like take, takeUntil, takeWhile, ect let you use a more declarative style to manage subscriptions.
Where possible, these are preferable as they're all less likely to cause strange errors or confusion within a team that is using them.
The examples above re-written:
of(1,2,3,4,5).pipe(
tap(console.log)
first(v => v === 4)
).subscribe();
It's working method, but RxJS mainly recommend use async pipe in Angular. That's the perfect solution. In your example you assign result to the object property and that's not a good practice.
If you use your variable in the template, then just use async pipe. If you don't, just make it observable in that way:
private readonly result$ = someObservable.pipe(/...get exactly what you need here.../)
And then you can use your result$ in cases when you need it: in other observable or template.
Also you can use pipe(take(1)) or pipe(first()) for unsubscribing. There are also some other pipe methods allowing you unsubscribe without additional code.
There are various ways of unsubscribing data:
Method 1: Unsubscribe after subscription; (Not preferred)
let localSubscription = someObservable.subscribe(result => {
this.result = result;
}).unsubscribe();
---------------------
Method 2: If you want only first one or 2 values, use take operator or first operator
a) let localSubscription =
someObservable.pipe(take(1)).subscribe(result => {
this.result = result;
});
b) let localSubscription =
someObservable.pipe(first()).subscribe(result => {
this.result = result;
});
---------------------
Method 3: Use Subscription and unsubscribe in your ngOnDestroy();
let localSubscription =
someObservable.subscribe(result => {
this.result = result;
});
ngOnDestroy() { this.localSubscription.unsubscribe() }
----------------------
Method 4: Use Subject and takeUntil Operator and destroy in ngOnDestroy
let destroySubject: Subject<any> = new Subject();
let localSubscription =
someObservable.pipe(takeUntil(this.destroySubject)).subscribe(result => {
this.result = result;
});
ngOnDestroy() {
this.destroySubject.next();
this.destroySubject.complete();
}
I would personally prefer method 4, because you can use the same destroy subject for multiple subscriptions if you have in a single page.
Let's imagine the next piece of Kotlin code that performs some query to a database by means a JDBC connector:
var results : ResultSet
preparedStatement.clearParameters()
preparedStatement.setInt(1,value1);
preparedStatement.setInt(2,value2)
results = preparedStatement.executeQuery()
while(results.next()) {
// parse results
}
that compiles without problems. However, when I try to add thread safety to the access to the preparedStatement:
var results : ResultSet
synchronized(preparedStatement) {
preparedStatement.clearParameters()
preparedStatement.setInt(1,value1);
preparedStatement.setInt(2,value2)
results = preparedStatement.executeQuery()
}
while(results.next()) {
// parse results
}
... I got a "Variable 'results' must be initialized". It seems the synchronized block acts as a conditional block, but you can be sure that it will be executed once, before the while block.
I have implemented this same block in Java and I don't get the error. Is this a design/implementation error of Kotlin? Or does it have a good reason to behave like that?
synchronized is just an inline function and compiler doesn't know if lambda will be executed once, or even executed at all. Idiomatic way is to return value from lambda and assign it to the local:
val results =
synchronized(preparedStatement) {
preparedStatement.clearParameters()
preparedStatement.setInt(1,value1);
preparedStatement.setInt(2,value2)
preparedStatement.executeQuery()
}
I can check for the input and if it's an invalid input from the user, I can use a simple "if condition" which prints "input invalid, please re-enter" (in case there is an invalid input).
This approach of "if there is a potential for a failure, verify it using an if condition and then specify the right behavior when failure is encountered..." seems enough for me.
If I can basically cover any kind of failure (divide by zero, etc.) with this approach, why do I need this whole exception handling mechanism (exception class and objects, checked and unchecked, etc.)?
Suppose you have func1 calling func2 with some input.
Now, suppose func2 fails for some reason.
Your suggestion is to handle the failure within func2, and then return to func1.
How will func1 "know" what error (if any) has occurred in func2 and how to proceed from that point?
The first solution that comes to mind is an error-code that func2 will return, where typically, a zero value will represent "OK", and each of the other (non-zero) values will represent a specific error that has occurred.
The problem with this mechanism is that it limits your flexibility in adding / handling new error-codes.
With the exception mechanism, you have a generic Exception object, which can be extended to any specific type of exception. In a way, it is similar to an error-code, but it can contain more information (for example, an error-message string).
You can still argue of course, "well, what's the try/catch for then? why not simply return this object?".
Fortunately, this question has already been answered here in great detail:
In C++ what are the benefits of using exceptions and try / catch instead of just returning an error code?
In general, there are two main advantages for exceptions over error-codes, both of which are different aspects of correct coding:
With an exception, the programmer must either handle it or throw it "upwards", whereas with an error-code, the programmer can mistakenly ignore it.
With the exception mechanism you can write your code much "cleaner" and have everything "automatically handled", wheres with error-codes you are obliged to implement a "tedious" switch/case, possibly in every function "up the call-stack".
Exceptions are a more object-oriented approach to handling exceptional execution flows than return codes. The drawback of return codes is that you have to come up with 'special' values to indicate different types of exceptional results, for example:
public double calculatePercentage(int a, int b) {
if (b == 0) {
return -1;
}
else {
return 100.0 * (a / b);
}
}
The above method uses a return code of -1 to indicate failure (because it cannot divide by zero). This would work, but your calling code needs to know about this convention, for example this could happen:
public double addPercentages(int a, int b, int c, int d) {
double percentage1 = calculatePercentage(a, b);
double percentage2 = calculatePercentage(c, c);
return percentage1 + percentage2;
}
Above code looks fine at first glance. But when b or d are zero the result will be unexpected. calculatePercentage will return -1 and add it to the other percentage which is likely not correct. The programmer who wrote addPercentages is unaware that there is a bug in this code until he tests it, and even then only if he really checks the validity of the results.
With exceptions you could do this:
public double calculatePercentage(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Second argument cannot be zero");
}
else {
return 100.0 * (a / b);
}
}
Code calling this method will compile without exception handling, but it will stop when run with incorrect values. This is often the preferred way since it leaves it up to the programmer if and where to handle exceptions.
If you want to force the programmer to handle this exception you should use a checked exception, for example:
public double calculatePercentage(int a, int b) throws MyCheckedCalculationException {
if (b == 0) {
throw new MyCheckedCalculationException("Second argument cannot be zero");
}
else {
return 100.0 * (a / b);
}
}
Notice that calculatePercentage has to declare the exception in its method signature. Checked exceptions have to be declared like that, and the calling code either has to catch them or declare them in their own method signature.
I think many Java developers currently agree that checked exceptions are bit invasive so most API's lately gravitate towards the use of unchecked exceptions.
The checked exception above could be defined like this:
public class MyCheckedCalculationException extends Exception {
public MyCalculationException(String message) {
super(message);
}
}
Creating a custom exception type like that makes sense if you are developing a component with multiple classes and methods which are used by several other components and you want to make your API (including exception handling) very clear.
(see the Throwable class hierarchy)
Let's assume that you need to write some code for some object, which consists of n different resources (n > 3) to be allocated in the constructor and deallocated inside the destructor.
Let's even say, that some of these resources depend on each other.
E.g. in order to create an memory map of some file one would first have to successfully open the file and then perform the OS function for memory mapping.
Without exception handling you would not be able to use the constructor(s) to allocate these resources but you would likely use two-step-initialization.
You would have to take care about order of construction and destruction yourself
-- since you're not using the constructor anymore.
Without exception handling you would not be able to return rich error information to the caller -- this is why in exception free software one usually needs a debugger and debug executable to identify why some complex piece of software is suddenly failing.
This again assumes, that not every library is able to simply dump it's error information to stderr. stderr is in certain cases not available, which in turn makes all code which is using stderr for error reporting not useable.
Using C++ Exception Handling you would simply chain the classes wrapping the matching system calls into base or member class relationships AND the compiler would take care about order of construction and destruction and to only call destructors for not failed constructors.
To start with, methods are generally the block of codes or statements in a program that gives the user the ability to reuse the same code which is ultimately the saving on the excessive use of memory. This means that there is now no wastage of memory on the computer.
How much information hiding is necessary? I have boilerplate code before I delete a record, it looks like this:
public override void OrderProcessing_Delete(Dictionary<string, object> pkColumns)
{
var c = Connect();
using (var cmd = new NpgsqlCommand("SELECT COUNT(*) FROM orders WHERE order_id = :_order_id", c)
{ Parameters = { {"_order_id", pkColumns["order_id"]} } } )
{
var count = (long)cmd.ExecuteScalar();
// deletion's boilerplate code...
if (count == 0) throw new RecordNotFoundException();
else if (count > 1) throw new DatabaseStructureChangedException();
// ...boiler plate code
}
// deleting of table(s) goes here...
}
NOTE: boilerplate code is code-generated, including the "using (var cmd = new NpgsqlCommand( ... )"
But I'm seriously thinking to refactor the boiler plate code, I wanted a more succint code. This is how I envision to refactor the code (made nicer with extension method (not the sole reason ;))
using (var cmd = new NpgsqlCommand("SELECT COUNT(*) FROM orders WHERE order_id = :_order_id", c)
{ Parameters = { {"_order_id", pkColumns["order_id"]} } } )
{
cmd.VerifyDeletion(); // [EDIT: was ExecuteWithVerification before]
}
I wanted the executescalar and the boilerplate code to goes inside the extension method.
For my code above, does it warrants code refactoring / information hiding? Is my refactored operation looks too opaque?
I would say that your refactor is extremely good, if your new single line of code replaces a handful of lines of code in many places in your program. Especially since the functionality is going to be the same in all of those places.
The programmer coming after you and looking at your code will simply look at the definition of the extension method to find out what it does, and now he knows that this code is defined in one place, so there is no possibility of it differing from place to place.
Try it if you must, but my feeling is it's not about succinctness but whether or not you want to enforce the behavior every time or most of the time. And by extension, if the verify-condition changes that it would likely change across the board.
Basically, reducing a small chunk of boiler-plate code doesn't necessarily make things more succinct; it's just one more bit of abstractness the developer has to wade through and understand.
As a developer, I'd have no idea what "ExecuteWithVerify" means. What exactly are we verifying? I'd have to look it up and remember it. But with the boiler-plate code, I can look at the code and understand exactly what's going on.
And by NOT reducing it to a separate method I can also tune the boiler-plate code for cases where exceptions need to be thrown for differing conditions.
It's not information-hiding when you extract or refactor your code. It's only information-hiding when you start restricting access to your extension definition after refactoring.
"new" operator within a Class (except for the Constructor) should be Avoided at all costs. This is what you need to refactor here.
So I have an abstract data type called RegionModel with a series of values (Region), each mapped to an index. It's possible to remove a number of regions by calling:
regionModel.removeRegions(index, numberOfRegionsToRemove);
My question is what's the best way to handle a call when the index is valid :
(between 0 (inclusive) and the number of Regions in the model (exclusive))
but the numberOfRegionsToRemove is invalid:
(index + regionsToRemove > the number of regions in the model)
Is it best to throw an exception like IllegalArgumentException or just to remove as many Regions as I can (all the regions from index to the end of the model)?
Sub-question: if I throw an exception what's the recommended way to unit test that the call threw the exception and left the model untouched (I'm using Java and JUnit here but I guess this isn't a Java specific question).
Typically, for structures like this, you have a remove method which takes an index and if that index is outside the bounds of the items in the structure, an exception is thrown.
That being said, you should be consistent with whatever that remove method that takes a single index does. If it simply ignores incorrect indexes, then ignore it if your range exceeds (or even starts before) the indexes of the items in your structure.
I agree with Mitchel and casperOne -- an Exception makes the most sense.
As far as unit testing is concerned, JUnit4 allows you to exceptions directly:
http://www.ibm.com/developerworks/java/library/j-junit4.html
You would need only to pass parameters which are guaranteed to cause the exception, and add the correct annotation (#Test(expected=IllegalArgumentException.class)) to the JUnit test method.
Edit: As Tom Martin mentioned, JUnit 4 is a decent-sized step away from JUnit 3. It is, however, possible to also test exceptions using JUnit 3. It's just not as easy.
One of the ways I've tested exceptions is by using a try/catch block within the class itself, and embedding Assert statements within it.
Here's a simple example -- it's not complete (e.g. regionModel is assumed to be instantiated), but it should get the idea across:
public void testRemoveRegionsInvalidInputs() {
int originalSize = regionModel.length();
int index = 0;
int numberOfRegionsToRemove = 1,000; // > than regionModel's current size
try {
regionModel.removeRegions(index, numberOfRegionsToRemove);
// Since the exception will immediately go into the 'catch' block this code will only run if the IllegalArgumentException wasn't thrown
Assert.assertTrue("Exception not Thrown!", false);
}
catch (IllegalArgumentException e) {
Assert.assertTrue("Exception thrown, but regionModel was modified", regionModel.length() == originalSize);
}
catch (Exception e) {
Assert.assertTrue("Incorrect exception thrown", false);
}
}
I would say that an argument such as illegalArgumentException would be the best way to go here. If the calling code was not passing a workable value, you wouldn't necessarily want to trust that they really wanted to remove what it had them do.