Junit --Exception testen

tanzverfuehrung

Bekanntes Mitglied
Guten tag, also ich teste grad meine Klasse...und in der Klasse wird eine exception gefangen und eine neue weiter geworfen!
ich weiß nicht wie ich das testen soll, WIe exceptions eigentlich zu testen sind, weiß ich!
doch das Funktioniert nicht oder welche von beiden muss ich überhaupt prüfen???

meine zu testende Klasse:
Java:
public class Function implements IFunction {

	private final ScriptEngine engine;

	public Function(ScriptEngine engine) {
		this.engine = engine;
	}
	/**
	 * Gibt für den übergebenen x Wert ,den errechneten y-Wert zurück.
	 * 
	 * @param x
	 *            übergebene xKoordinate
	 * @return yKoordinate
	 */
	@Override
	public double f(double x) {
		Object y;
		try {
			y = engine.eval("f(" + x + ");");
		}
		catch (ScriptException e) {
			throw new IllegalStateException(e.getMessage());
		}
		return ((Number) y).doubleValue();
	}
}

und der test sieht bis jetzt so aus:
Java:
	/**
	 * Prüft ob eine {@link IllegalStateException} geworfen wird, wenn falsche
	 * Werte übergeben werden.
	 * 
	 * @throws Exception
	 */
	@Test(expected = IllegalStateException.class)
	public void illegalState() throws Exception {
		
		function = math.eval("5x");
		function.f(1);
	}

kann mir jemand helfen????😱;(
 
Zuletzt bearbeitet:
Du musst deinem zu testenden Objekt eine [c]ScriptEngine[/c] (ein Mock) unterschieben, das beim Aufruf von eval() einfach eine ScriptException wirft. Hierfür würde sich ein Mocking-Framework anbieten.
 
Du musst deinem zu testenden Objekt eine [c]ScriptEngine[/c] (ein Mock) unterschieben, das beim Aufruf von eval() einfach eine ScriptException wirft. Hierfür würde sich ein Mocking-Framework anbieten.

ja also mit mocken ahbe ich es auch schon versucht!
aber da war nciht ein test bei mir grün!

der test zum Beipiel geht:
Java:
/**
	 * Prüft ob zu der linearen Funktion und dem übergeben x-Wert der richtige y-Wert
	 * errechnet wird.
	 * 
	 * @throws Exception
	 */
	@Test
	public void linearFunction() throws Exception {
		function = math.eval("5*x+1");
		Object result = function.f(-2.0);
		Object y = -9.0;
		assertThat(((Number) result).doubleValue(), is(((Number) y).doubleValue()));
	}
aber ist der falsch oder was???
 
Du musst deinem zu testenden Objekt eine [c]ScriptEngine[/c] (ein Mock) unterschieben, das beim Aufruf von eval() einfach eine ScriptException wirft. Hierfür würde sich ein Mocking-Framework anbieten.

meinst du so????:shock:
Java:
	/**
	 * Prüft ob eine {@link IllegalStateException} geworfen wird, wenn falsche
	 * Werte übergeben werden.
	 * 
	 * @throws Exception
	 */
	@Test
	public void illegalState() throws Exception {
		//@formatter:off
		context.checking(new Expectations() {{
			oneOf(engine).eval("sf");
				will(returnValue(ScriptException.class));
		}});
		//@formatter:on
		function.f(1);
	}
}

die zeile muss aufjedenfall bleiben oder???
Java:
 @Test(expected = IllegalStateException.class)

oder muss die andere Exception da hin?
Java:
 @Test(expected = ScriptException.class)
 
Zuletzt bearbeitet:
Ich seh nicht so recht, wo da gemockt wird.
Mit JMockit würde ich es so machen:
Java:
@Mocked
private ScriptEngine engine;

@Test(expected = IllegalStateException.class))
public void scriptExceptionIsForwardedAsIllegalArgumentException() {
    Function func = new Function(engine);
    new Expectations() {
        {
            engine.eval(anyString);
            result=new IllegalArgumentException();
        }
    };
    func.f(0.0);
}
In diesem einfachen Fall geht es sicher auch ganz gut ohne Mocking-Framework.

Edit: OK, jetzt seh ich auch dein Mocking.
 
ich habe es nun mal so probiert aber das geht immer noch nicht, im meiner console sagt er mir:
java.lang.Exception: Unexpected exception, expected<java.lang.IllegalStateException> but was<java.lang.AssertionError>

Java:
	/**
	 * Prüft ob eine {@link IllegalStateException} geworfen wird, wenn falsche
	 * Werte übergeben werden.
	 * 
	 * @throws Exception
	 */
	@Test(expected = IllegalStateException.class)
	public void illegalState() throws Exception {
	function =new Function(engine);
	
	//@formatter:off
		context.checking(new Expectations() {{
		engine.eval("abc");
	            result= new ScriptException("");
		}});
		//@formatter:on

	    function.f(0.0);
//		assertThat(function.f(0.0), is(result));;
	}
}
;(;(


und ich habe mocking auch bisschen anders gelernt und habe es noch mal so implementiert und da kommt eine andere fehler meldung, was ja noch kurioser ist!!!

ist doch eigentlich das gleiche oder?

Java:
	/**
	 * Prüft ob eine {@link IllegalStateException} geworfen wird, wenn falsche
	 * Werte übergeben werden.
	 * 
	 * @throws Exception
	 */
	@Test(expected = IllegalStateException.class)
	public void illegalState() throws Exception {
	function =new Function(engine);
	
		//@formatter:off
		context.checking(new Expectations() {{
		oneOf(engine).eval("abc");
				will(returnValue(new ScriptException("")));
		}});
		//@formatter:on

	    function.f(0.0);
//		assertThat(function.f(0.0), is(result));;
	}
}

fehlermeldung:
java.lang.Exception: Unexpected exception, expected<java.lang.IllegalStateException> but was<java.lang.AssertionError>
???:L
 
Zuletzt bearbeitet:
Der Code sieht eigentlich gut aus. Wo fliegt denn der AssertionError? Ist das assertThat wirklich auskommentiert? Mach mal Clean und Rebuild.
 
Da sollte auch ein Stacktrace mit Zeilennummer stehen.

java.lang.Exception: Unexpected exception, expected<java.lang.IllegalStateException> but was<java.lang.AssertionError>
Caused by: java.lang.AssertionError: unexpected invocation: scriptEngine.eval("f(0.0);")
expectations:
expected once, never invoked: scriptEngine.eval("abc"); returns <javax.script.ScriptException: >
what happened before this: nothing!
 
Steht doch da. Die Expectations erwarten, dass [c]eval("abc")[/c] aufgerufen wird. Du rufst aber [c]eval("f(0.0);")[/c] auf.
 
Steht doch da. Die Expectations erwarten, dass [c]eval("abc")[/c] aufgerufen wird. Du rufst aber [c]eval("f(0.0);")[/c] auf.

Java:
@Test(expected = IllegalStateException.class)
	public void illegalState() throws Exception {
		function = new Function(engine);

		//@formatter:off
		context.checking(new Expectations() {{
		oneOf(engine).eval("f(0.0);");
				will(returnValue(new ScriptException("")));
		}});
		//@formatter:on
		 Object result = function.f(0.0);
	((Number)result).doubleValue();
	}
}
so geht es nciht, da kommt nun eine classCastException

und auserdem will ich ja gucken ob die exception weiter geworfen wird,deswegen muss ich ja ein Fehler einbauen oder nicht?????????:L
 
da kommt nun eine classCastException
Aha. Dann musst du die beheben.

und auserdem will ich ja gucken ob die exception weiter geworfen wird,deswegen muss ich ja ein Fehler einbauen oder nicht??????
Das tust du ja, indem du die ScriptException erzeugst. Allerdings weiß ich nicht, ob das korrekt mit dem will(returnValue(..)) funktioniert, den die Exception muss ja geworfen werden und nicht mit return zurück geliefert. Ich weiß nicht, was für ein Mocker du benutzt, mit JMockit geht es so wie oben beschrieben.

Edit: Ich seh grad, in meinem Beispiel ist ein Fehler. In Zeile 10 muss natürlich ScriptException stehen.
 
Zuletzt bearbeitet:
Aha. Dann musst du die beheben.


Das tust du ja, indem du die ScriptException erzeugst. Allerdings weiß ich nicht, ob das korrekt mit dem will(returnValue(..)) funktioniert, den die Exception muss ja geworfen werden und nicht mit return zurück geliefert. Ich weiß nicht, was für ein Mocker du benutzt, mit JMockit geht es so wie oben beschrieben.

Edit: Ich seh grad, in meinem Beispiel ist ein Fehler. In Zeile 10 muss natürlich ScriptException stehen.

Ich benutze JMock und ich kenne das nur nach dem schema ...
bei deinem code beispiel hat mich das result so verwirrt!?muss ich damit nicht irgendwas machen?
oder so???


Java:
@Mocked
private ScriptEngine engine;
 
@Test(expected = IllegalStateException.class))
public void scriptExceptionIsForwardedAsIllegalArgumentException() {
    Function func = new Function(engine);
    new Expectations() {
        {
            engine.eval(anyString);
            result=new ScriptException();
        }
    };
    func.f(0.0);
}
 
Mit [c]result=...[/c] legt man fest, was die gemockte Methode als ergebnis zurückliefert ([c]returns(...)[/c] gibt's auch, aber das funktioniert etwas anders). Wenn das Objekt, das man result zuweist, ein Throwable ist, wirft die Methode dieses Throwable. Genau das willst du erreichen. Finde heraus, wie das mit JMock funktioniert, und der Test sollte klappen. Das returnValue gibt die Exception wahrscheinlich nur als Ergebnis zurück - was auch die ClassCastException erklären würde.
 
Mit JMock sieht das irgendwie facked aus... Hier mal EasyMock

Java:
private ScriptEngine engine = createMock(ScriptEngine.class);
 
@Test(expected=IllegalStateException.class))
public void scriptExceptionIsForwardedAsIllegalArgumentException() {
    Function func = new Function(engine);
    expect(engine.eval(isA(String.class))).andThrows(new ScriptException("tattaa ! exception ist daa!"));
    replay(engine); // oder replayAll wenn Dein Test EasyMockSupported, verify() und reset() ins tearDown
    func.f(0.0);
}
 

Zurück
Oben