# Junit --Exception testen



## tanzverfuehrung (4. Apr 2012)

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:

```
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:

```
/**
	 * 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????;(


----------



## tfa (4. Apr 2012)

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.


----------



## tanzverfuehrung (4. Apr 2012)

tfa hat gesagt.:


> 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:

```
/**
	 * 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???


----------



## tanzverfuehrung (4. Apr 2012)

tfa hat gesagt.:


> 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:

```
/**
	 * 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???

```
@Test(expected = IllegalStateException.class)
```

oder muss die andere Exception da hin?

```
@Test(expected = ScriptException.class)
```


----------



## tfa (4. Apr 2012)

Ich seh nicht so recht, wo da gemockt wird.
Mit JMockit würde ich es so machen:

```
@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.


----------



## tanzverfuehrung (4. Apr 2012)

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>




```
/**
	 * 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?


```
/**
	 * 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


----------



## tfa (4. Apr 2012)

Der Code sieht eigentlich gut aus. Wo fliegt denn der AssertionError? Ist das assertThat wirklich auskommentiert? Mach mal Clean und Rebuild.


----------



## tanzverfuehrung (4. Apr 2012)

tfa hat gesagt.:


> Wo fliegt denn der AssertionError?


das würde mich mal auch interessieren...haha:shock::lol:



tfa hat gesagt.:


> Ist das assertThat wirklich auskommentiert? Mach mal Clean und Rebuild.


ja war auskommentiert!
und mach ich mal!


ich danke dir aufjedenfall schon mal herzlich!:toll:


----------



## tfa (4. Apr 2012)

> das würde mich mal auch interessieren


Da sollte auch ein Stacktrace mit Zeilennummer stehen.


----------



## tanzverfuehrung (5. Apr 2012)

tfa hat gesagt.:


> 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!


----------



## tfa (5. Apr 2012)

Steht doch da. Die Expectations erwarten, dass [c]eval("abc")[/c] aufgerufen wird. Du rufst aber [c]eval("f(0.0);")[/c] auf.


----------



## tanzverfuehrung (5. Apr 2012)

tfa hat gesagt.:


> Steht doch da. Die Expectations erwarten, dass [c]eval("abc")[/c] aufgerufen wird. Du rufst aber [c]eval("f(0.0);")[/c] auf.




```
@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


----------



## tfa (5. Apr 2012)

> 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.


----------



## tanzverfuehrung (5. Apr 2012)

tfa hat gesagt.:


> 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.
> ...



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???



```
@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);
}
```


----------



## tfa (5. Apr 2012)

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.


----------



## fastjack (5. Apr 2012)

Mit JMock sieht das irgendwie facked aus... Hier mal EasyMock


```
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);
}
```


----------

