How to Spec Methods That Exit or Abort

How to spec methods that exit or abort

Simply put your assertions outside of the lambda, for example:

class Foo
attr_accessor :result

def logic_and_exit
@result = :bad_logic
exit
end
end

describe 'Foo#logic_and_exit' do
before(:each) do
@foo = Foo.new
end

it "should set @foo" do
lambda { @foo.logic_and_exit; exit }.should raise_error SystemExit
@foo.result.should == :logics
end
end

When I run rspec, it correctly tells me:

expected: :logics
got: :bad_logic (using ==)

Is there any case where this wouldn't work for you?

EDIT: I added an 'exit' call inside the lambda to hande the case where logic_and_exit doesn't exit.

EDIT2: Even better, just do this in your test:

begin
@foo.logic_and_exit
rescue SystemExit
end
@foo.result.should == :logics

How can I validate exits and aborts in RSpec?

try this:

module MyGem
describe "CLI" do
context "execute" do

it "should exit cleanly when -h is used" do
argv=["-h"]
out = StringIO.new
lambda { ::MyGem::CLI.execute( out, argv) }.should raise_error SystemExit
end

end
end
end

Test exit! with RSpec

You can stub the exit! method for the object:

it "logs a fatal error" do
lambda do
allow(object).to receive(:exit!)
object.method
expect(logger).to have_received(:error).with("FATAL ERROR")
end
end

it "exits" do
expect(object).to receive(:exit!)

object.method
end

Early exit from function?

You can just use return.

function myfunction() {
if(a == 'stop')
return;
}

This will send a return value of undefined to whatever called the function.

var x = myfunction();

console.log( x ); // console shows undefined

Of course, you can specify a different return value. Whatever value is returned will be logged to the console using the above example.

return false;
return true;
return "some string";
return 12345;

How to abort a thread in a fast and clean way in java?

Try interrupt() as some have said to see if it makes any difference to your thread. If not, try destroying or closing a resource that will make the thread stop. That has a chance of being a little better than trying to throw Thread.stop() at it.

If performance is tolerable, you might view each 3D update as a discrete non-interruptible event and just let it run through to conclusion, checking afterward if there's a new latest update to perform. This might make the GUI a little choppy to users, as they would be able to make five changes, then see the graphical results from how things were five changes ago, then see the result of their latest change. But depending on how long this process is, it might be tolerable, and it would avoid having to kill the thread. Design might look like this:

boolean stopFlag = false;
Object[] latestArgs = null;

public void run() {
while (!stopFlag) {
if (latestArgs != null) {
Object[] args = latestArgs;
latestArgs = null;
perform3dUpdate(args);
} else {
Thread.sleep(500);
}
}
}

public void endThread() {
stopFlag = true;
}

public void updateSettings(Object[] args) {
latestArgs = args;
}

Way to exit from the method

Technically you could System.exit(int) (the int value would be the value returned from the process and likely non-zero to indicate an error). It's a little brutal, however.

You can also interrupt yourself.

Thread.currentThread().interrupt();

However:

  1. this is still an exception. You're not throwing it explicitly, but it still results in an InterruptedException
  2. your thread has to perform some IO/sleep operation subsequently to register this interruption. If it's solely computational then it won't exit due to this.

e.g. (note the sleep() to catch the interruption):

public class Test {
public static void method() throws Exception {
Thread.currentThread().interrupt();
Thread.sleep(100);
System.out.println("method done");
}
public static void main(String[] args) throws Exception {
method();
System.out.println("done");
}
}

gives me:

Exception in thread "main" java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at T.method(T.java:5)
at T.main(T.java:9)


Related Topics



Leave a reply



Submit