1616
1717package  org .springframework .ai .template .st ;
1818
19+ import  static  org .assertj .core .api .Assertions .*;
20+ 
21+ import  java .io .ByteArrayOutputStream ;
22+ import  java .io .PrintStream ;
23+ import  java .nio .charset .StandardCharsets ;
1924import  java .util .HashMap ;
2025import  java .util .Map ;
2126
2227import  org .junit .jupiter .api .Test ;
23- 
28+ import   org . slf4j . LoggerFactory ; 
2429import  org .springframework .ai .template .ValidationMode ;
2530import  org .springframework .test .util .ReflectionTestUtils ;
2631
27- import  static  org .assertj .core .api .Assertions .assertThat ;
28- import  static  org .assertj .core .api .Assertions .assertThatThrownBy ;
32+ import  ch .qos .logback .classic .Level ;
33+ import  ch .qos .logback .classic .Logger ;
34+ import  ch .qos .logback .classic .spi .ILoggingEvent ;
35+ import  ch .qos .logback .core .read .ListAppender ;
2936
3037/** 
3138 * Unit tests for {@link StTemplateRenderer}. 
@@ -37,8 +44,8 @@ class StTemplateRendererTests {
3744	@ Test 
3845	void  shouldNotAcceptNullValidationMode () {
3946		assertThatThrownBy (() -> StTemplateRenderer .builder ().validationMode (null ).build ())
40- 			.isInstanceOf (IllegalArgumentException .class )
41- 			.hasMessageContaining ("validationMode cannot be null" );
47+ 				 .isInstanceOf (IllegalArgumentException .class )
48+ 				 .hasMessageContaining ("validationMode cannot be null" );
4249	}
4350
4451	@ Test 
@@ -80,14 +87,14 @@ void shouldNotRenderEmptyTemplate() {
8087		Map <String , Object > variables  = new  HashMap <>();
8188
8289		assertThatThrownBy (() -> renderer .apply ("" , variables )).isInstanceOf (IllegalArgumentException .class )
83- 			.hasMessageContaining ("template cannot be null or empty" );
90+ 				 .hasMessageContaining ("template cannot be null or empty" );
8491	}
8592
8693	@ Test 
8794	void  shouldNotAcceptNullVariables () {
8895		StTemplateRenderer  renderer  = StTemplateRenderer .builder ().build ();
8996		assertThatThrownBy (() -> renderer .apply ("Hello!" , null )).isInstanceOf (IllegalArgumentException .class )
90- 			.hasMessageContaining ("variables cannot be null" );
97+ 				 .hasMessageContaining ("variables cannot be null" );
9198	}
9299
93100	@ Test 
@@ -98,7 +105,7 @@ void shouldNotAcceptVariablesWithNullKeySet() {
98105		variables .put (null , "Spring AI" );
99106
100107		assertThatThrownBy (() -> renderer .apply (template , variables )).isInstanceOf (IllegalArgumentException .class )
101- 			.hasMessageContaining ("variables keys cannot be null" );
108+ 				 .hasMessageContaining ("variables keys cannot be null" );
102109	}
103110
104111	@ Test 
@@ -108,7 +115,7 @@ void shouldThrowExceptionForInvalidTemplateSyntax() {
108115		variables .put ("name" , "Spring AI" );
109116
110117		assertThatThrownBy (() -> renderer .apply ("Hello {name!" , variables )).isInstanceOf (IllegalArgumentException .class )
111- 			.hasMessageContaining ("The template string is not valid." );
118+ 				 .hasMessageContaining ("The template string is not valid." );
112119	}
113120
114121	@ Test 
@@ -118,9 +125,9 @@ void shouldThrowExceptionForMissingVariablesInThrowMode() {
118125		variables .put ("greeting" , "Hello" );
119126
120127		assertThatThrownBy (() -> renderer .apply ("{greeting} {name}!" , variables ))
121- 			.isInstanceOf (IllegalStateException .class )
122- 			.hasMessageContaining (
123- 					"Not all variables were replaced in the template. Missing variable names are: [name]" );
128+ 				 .isInstanceOf (IllegalStateException .class )
129+ 				 .hasMessageContaining (
130+ 						 "Not all variables were replaced in the template. Missing variable names are: [name]" );
124131	}
125132
126133	@ Test 
@@ -148,9 +155,9 @@ void shouldRenderWithoutValidationInNoneMode() {
148155	@ Test 
149156	void  shouldRenderWithCustomDelimiters () {
150157		StTemplateRenderer  renderer  = StTemplateRenderer .builder ()
151- 			.startDelimiterToken ('<' )
152- 			.endDelimiterToken ('>' )
153- 			.build ();
158+ 				 .startDelimiterToken ('<' )
159+ 				 .endDelimiterToken ('>' )
160+ 				 .build ();
154161		Map <String , Object > variables  = new  HashMap <>();
155162		variables .put ("name" , "Spring AI" );
156163
@@ -162,9 +169,9 @@ void shouldRenderWithCustomDelimiters() {
162169	@ Test 
163170	void  shouldHandleSpecialCharactersAsDelimiters () {
164171		StTemplateRenderer  renderer  = StTemplateRenderer .builder ()
165- 			.startDelimiterToken ('$' )
166- 			.endDelimiterToken ('$' )
167- 			.build ();
172+ 				 .startDelimiterToken ('$' )
173+ 				 .endDelimiterToken ('$' )
174+ 				 .build ();
168175		Map <String , Object > variables  = new  HashMap <>();
169176		variables .put ("name" , "Spring AI" );
170177
@@ -297,4 +304,34 @@ void shouldRenderTemplateWithBuiltInFunctions() {
297304		assertThat (result ).isEqualTo ("Hello!" );
298305	}
299306
307+ 	@ Test 
308+ 	void  malformedTemplateShouldLogErrorViaSlf4j () {
309+ 		Logger  logger  = (Logger ) LoggerFactory .getLogger (StTemplateRenderer .class );
310+ 		ListAppender <ILoggingEvent > appender  = new  ListAppender <>();
311+ 		appender .start ();
312+ 		logger .addAppender (appender );
313+ 
314+ 		PrintStream  originalErr  = System .err ;
315+ 		ByteArrayOutputStream  err  = new  ByteArrayOutputStream ();
316+ 		System .setErr (new  PrintStream (err ));
317+ 		try  {
318+ 			StTemplateRenderer  renderer  = StTemplateRenderer .builder ().build ();
319+ 			Map <String , Object > variables  = new  HashMap <>();
320+ 			variables .put ("name" , "Spring AI" );
321+ 			assertThatThrownBy (() -> renderer .apply ("Hello {name!" , variables ))
322+ 					.isInstanceOf (IllegalArgumentException .class );
323+ 		}
324+ 		finally  {
325+ 			System .setErr (originalErr );
326+ 			logger .detachAppender (appender );
327+ 			appender .stop ();
328+ 		}
329+ 
330+ 		assertThat (appender .list ).isNotEmpty ();
331+ 		ILoggingEvent  event  = appender .list .get (0 );
332+ 		assertThat (event .getLevel ()).isEqualTo (Level .ERROR );
333+ 		assertThat (event .getFormattedMessage ()).contains ("StringTemplate compile error" );
334+ 		assertThat (err .toString (StandardCharsets .UTF_8 )).isEmpty ();
335+ 	}
336+ 
300337}
0 commit comments