Eclipse Scout client unit tests with ScoutClientTestRunner - unit-testing

I am trying to create unit test with scout context and I can't find proper tutorial or example for it.
When I create test with ScoutClientTestRunner, I get error
java.lang.Exception: Client session class is not set. Either set the default client session using 'ScoutClientTestRunner.setDefaultClientSessionClass' or annotate your test class and/or method with 'ClientTest'
I try to set client session class like this :
#Before
public void setClassSession() throws Exception {
ScoutClientTestRunner.setDefaultClientSessionClass(ClientSession.class)
}
and
#BeforeClass
public void setClassSession() throws Exception {
ScoutClientTestRunner.setDefaultClientSessionClass(ClientSession.class);
}
I try to add #ClientTest to the class and to all methods but I still get same error.
How to set client session in tests if you use ScoutClientTestRunner ?

The ScoutClientTestRunner ensures that the JUnit tests are executed having all the Scout Context (OSGi and so on) available.
Your attempts with #Before or #BeforeClass are too late. You need to provide the Scout Context initialization parameters before that. As the exception message says, you have 2 possibilities:
(1) #ClientTest annotation
You can annotate test classes or methods with #ClientTest using the clientSessionClass parameter:
#RunWith(ScoutClientTestRunner.class)
#ClientTest(clientSessionClass = ClientSession.class)
public class DesktopFormTest {
#Test
public void test1() throws Exception {
//Do something requiring a scout context:
//for example instantiate a DesktopForm.
}
}
If necessary you can also do it at method level:
#RunWith(ScoutClientTestRunner.class)
public class DesktopFormTest {
#Test
#ClientTest(clientSessionClass = Client1Session.class)
public void test1() throws Exception {
//client session is an instance of Client1Session.
}
#Test
#ClientTest(clientSessionClass = Client2Session.class)
public void test2() throws Exception {
//client session is an instance of Client2Session.
}
}
(2) Defining a TestEnvironment
When the test is run (directly or using maven-tycho), a lookup for a fully qualified class org.eclipse.scout.testing.client.runner.CustomClientTestEnvironment is done.
The CustomClientTestEnvironment class should implement org.eclipse.scout.testing.client.runner.IClientTestEnvironment
The method setupGlobalEnvironment() is called once and can be used to define the default client session with ScoutClientTestRunner.setDefaultClientSessionClass(..). This method can also be used to register required services.
Here an example:
package org.eclipse.scout.testing.client.runner; // <= can not be changed.
// add imports
public class CustomClientTestEnvironment implements IClientTestEnvironment {
#Override
public void setupGlobalEnvironment() {
//Set client session:
ScoutClientTestRunner.setDefaultClientSessionClass(ClientSession.class);
}
#Override
public void setupInstanceEnvironment() {
}
}
Of course (1) and (2) are compatible. The second mechanism defines only the default and ClientSession configured with (1) will override the default.

Related

Spring Boot #Async not working

I expect that uploadImage method finishes once the file is uploaded to AWS, while scanFile method is still running asynchronously in the background;
#RestController
public class EmailController {
#PostMapping("/upload")
#ResponseStatus(HttpStatus.OK)
public void uploadImage(#RequestParam MultipartFile photos) {
awsAPIService.uploadImage(photos);
}
}
...
#Service
public class AwsAPIService {
public void uploadImage(MultipartFile file) {
try {
File fileToUpload = this.convertMultiPartToFile(file);
String fileName = this.generateFileName(file);
s3client.putObject(new PutObjectRequest(AWS_S3_QUARANTINE_BUCKET_NAME,fileName, fileToUpload));
fileToUpload.delete();
// start scan file
scanFile();
} ...
}
#Async
public void scanFile() {
log.info("Start scanning");
String queueUrl = sqs.getQueueUrl("bucket-antivirus").getQueueUrl();
List<Message> messages = sqs.receiveMessage(new ReceiveMessageRequest().withQueueUrl(queueUrl)
.withWaitTimeSeconds(20)).getMessages();
for (Message message : messages) {
// delete message
...
}
}
}
...
#EnableAsync
public class AppConfig {
#Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(2);
taskExecutor.setQueueCapacity(200);
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
}
But this seems still running synchronously. What is the problem here?
By default #Async and other Spring method-level annotations like #Transactional work only on the external, bean-to-bean method call. An internal method call from uploadImage() to scanFile() in the same bean won't trigger the proxy implementing the Spring behaviour. As per Spring docs:
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with #Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. #PostConstruct.
You could configure AspectJ to enable annotations on internal method calls, but it's usually easier to refactor the code.

Wanted but not invoked: Mockito and Retrofit

I'm trying to unit test a call to my api using Mockito.
I took a look at all the issues already mentioned here on S.O together with the solutions, but so far, none of them have been conclusive.
MyService is an interface which holds several resources. Here's a sample:
public interface MyService {
#GET("/myresource")
Call<MyResponse> getDataFromServer();
}
Inside my Application class, I have a static class which returns an instance of MyService
public static MyService getApiService() {
return mApiService;
}
So, from there on inside one of my classes, I make the call to the web service:
Call<MyResponse> call = getApiService.getDataFromServer();
call.enqueue(myCallback)
The rest follows with the callback method being called....
Here's my test class:
#RunWith(AndroidJUnit4.class)
public class SampleTest {
#Mock
private MyService mService;
#Captor
private ArgumentCaptor<Callback<MyResponse>> callbackArgumentCaptor;
#Mock
private Call<MyResponse> mockCall;
// Rule to trigger the creation of #Mock annotated objects.
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Test
public void testDoAction() throws NullInsteadOfMockException {
when(mService.doSomeAction()).thenReturn(mockCall);
mService.doSomeAction();
verify(mockCall).enqueue(callbackArgumentCaptor.capture());
}
}
Here's the error I have once I run the test:
Wanted but not invoked:
mockCall.enqueue(
<Capturing argument>
);
Actually, there were zero interactions with this mock.
I have the same error even if use MockitoJunitRunner (in place of AndroidJunitRunner) and initialize my mock objects inside a setup method I define like this:
#Before
public void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
}
Mockito version : 2.7.19
I want to be able to test the API response, so I mocked the API service, defined a captor for the retrofit Callback
It's a bit strange what you're trying to do here. You're testing a class, but you mock it. You should test the real class - MyService. I assume that your service looks a bit like:
public class MyService {
private final Call<MyResponse> call;
public MyService(Call<MyResponse> call) {
this.call = call;
}
public void doSomeAction() {
call.enqueue(...);
}
}
Ideally you should have something like:
#RunWith(AndroidJUnit4.class)
public class SampleTest {
private MyService mService;
#Captor
private ArgumentCaptor<Callback<MyResponse>> callbackArgumentCaptor;
#Mock
private Call<MyResponse> mockCall;
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Before
public void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
mService = new MyService(mockCall);
}
#Test
public void testDoAction() throws NullInsteadOfMockException {
mService.doSomeAction();
verify(mockCall).enqueue(callbackArgumentCaptor.capture());
}
}
So the idea is to mock all the dependencies of the class you're unit testing and pass them to the class somehow. Here I'm injecting them in the constructor. I don't know if this is the case for you, but a setter or a field works too.
Then the test simply calls the real method in the service class and if this method is suppose to enqueue the call, then the verify should pass.
The reason it doesn't work in your case is because you're mocking the service so when you call mService.doSomeAction() this doesn't call your implementation, which I suppose should call enqueue. This is why the verify fails. In other words, it's true that enqueue is never called on the call object.

How to Mock DataSource Dependency Injection Despite Being Accessible via Static Method

I'm using Mockito, DBUnit and HSQLDB to unit test my database code. I'm also writing integration tests of course.
I'm having trouble understanding how to inject a mocked DataSource into the system under test (class I'm testing). The DataSource is used for connection pooling, and therefore other classes can call a static method in the same class in order to retrieve an instance of this DataSource. This means that the DataSource is not injected into any constructors, anywhere, and so my tests don't have any constructors to inject the mocked DataSource into.
I'm getting around this by altering the logic of my real code to check if a private variable is null, and if so then use the injected DataSource (bad design since it's only needed for tests), otherwise it calls the static method to retrieve the connection pool's source (better design).
How do I inject a mocked DataSource into a class that doesn't have a constructor set up to accept it, because it can instead just call the static method to retrieve the dependency?
Class to Test
public DBConnection(DBSource dbSource) { // <--- Constructor only required for test purposes :(
this.dbSource = dbSource;
}
public final void createCompsDB() {
Connection conn = null;
Statement statement = null;
try {
if(dbSource==null){
conn = DBSource.getInstance().getConnection();
}else{
conn = dbSource.getConnection(); /** Likely bad design, since dbSource is only NOT null for tests, so that you can inject the mocked datasource :( */
}
statement = conn.createStatement();
statement.executeUpdate("CREATE DATABASE placesdb");
System.out.println("Database created...");
} catch (SQLException e) {
// ...
}
} finally {
// Close Resources...
}
}
}
Test Class -- Test Passes
public class DBConnectionTest {
final Statement statement = mock(Statement.class);
final Connection connection = mock(Connection.class);
final DBSource dataSource = mock(DBSource.class);
#Before
public void setUp() throws SQLException, IOException, PropertyVetoException {
when(dataSource.getConnection()).thenReturn(connection);
when(connection.createStatement()).thenReturn(statement);
}
#Test
public void testCreateCompDBIfNotAlready() throws Exception {
DBConnection dbConnection = new DBConnection(localDB, dataSource); /** This constructor is only needed for testing :( . How do I avoid it since all the classes I need to test don't require the dependency to be injected? */
dbConnection.createCompsDB();
verify(statement).executeUpdate("CREATE DATABASE PLACES");
}
}
DBSource.java
protected DBSource() throws IOException, SQLException, PropertyVetoException {
ds = new BasicDataSource();
ds.setDriverClassName("org.postgresql.Driver");
ds.setUsername("user");
ds.setPassword("pass");
ds.setUrl("jdbc:postgresql://localhost:5432/placesdb");
}
public static DBSource getInstance() { // <--- Static method means dependent classes don't need to accept injections
if (datasource == null) {
datasource = new DBSource();
return datasource;
} else {
return datasource;
}
}
public Connection getConnection() throws SQLException {
return this.ds.getConnection();
}
}
Mocking of the static class methods may be done with PowerMockito.
The test class should be something like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(DBSource.class)
public class DBConnectionTest {
#Mock
final Statement statement;
#Mock
final Connection connection;
#Mock
final DBSource dbsource;
#Before
public void setUp() throws SQLException, IOException, PropertyVetoException {
PowerMockito.mockStatic(DBSource.class);
when(DbSource.getInstance()).thenReturn(dbsource);
when(dbsource.getConnection()).thenReturn(connection);
when(connection.createStatement()).thenReturn(statement);
}
#Test
public void testCreateCompDBIfNotAlready() throws Exception {
DBConnection dbConnection = new DBConnection(localDB); // No test-only constructor anymore
dbConnection.createCompsDB();
verify(statement).executeUpdate("CREATE DATABASE PLACES");
}
}
You can read here more about mocking with PowerMock.

How to unit test an interceptor?

I want to write some unit tests for an interceptor that intercepts the Loggable base class (which implements ILoggable).
The Loggable base class has no methods to call and it is used only to be initialized by the logging facility.
To my understanding I should:
Mock an ILoggable and an ILogger
Initialize the logging facility
Register my interceptor on it
Invoke some method of the mocked ILoggable
The problem is that my ILoggable interface has no methods to call and thus nothing will be intercepted.
What is the right way to act here?
Should I mock ILoggable manually and add a stub method to call?
Also, should I be mocking the container as well?
I am using Moq and NUnit.
EDIT:
Here's my interceptor implementation for reference:
public class LoggingWithDebugInterceptor : IInterceptor
{
#region IInterceptor Members
public void Intercept(IInvocation invocation)
{
var invocationLogMessage = new InvocationLogMessage(invocation);
ILoggable loggable = invocation.InvocationTarget as ILoggable;
if (loggable == null)
throw new InterceptionFailureException(invocation, string.Format("Class {0} does not implement ILoggable.", invocationLogMessage.InvocationSource));
loggable.Logger.DebugFormat("Method {0} called with arguments {1}", invocationLogMessage.InvokedMethod, invocationLogMessage.Arguments);
Stopwatch stopwatch = new Stopwatch();
try
{
stopwatch.Start();
invocation.Proceed();
stopwatch.Stop();
}
catch (Exception e)
{
loggable.Logger.ErrorFormat(e, "An exception occured in {0} while calling method {1} with arguments {2}", invocationLogMessage.InvocationSource, invocationLogMessage.InvokedMethod, invocationLogMessage.Arguments);
throw;
}
finally
{
loggable.Logger.DebugFormat("Method {0} returned with value {1} and took exactly {2} to run.", invocationLogMessage.InvokedMethod, invocation.ReturnValue, stopwatch.Elapsed);
}
}
#endregion IInterceptor Members
}
If it's just the interceptor that uses the Logger Property on your class than why have in there at all? You might just as well have it on the interceptor. (like Ayende explained in his post here).
Other than that - interceptor is just a class which interacts with an interface - everything highly testable.
I agree with Krzysztof, if you're looking to add Logging through AOP, the responsibility and implementation details about logging should be transparent to the caller. Thus it's something that the Interceptor can own. I'll try to outline how I would test this.
If I follow the question correctly, your ILoggable is really just a naming container to annotate the class so that the interceptor can determine if it should perform logging. It exposes a property that contains the Logger. (The downside to this is that the class still needs to configure the Logger.)
public interface ILoggable
{
ILogger { get; set; }
}
Testing the interceptor should be a straight-forward process. The only challenge I see that you've presented is how to manually construct the IInvocation input parameter so that it resembles runtime data. Rather than trying to reproduce this through mocks, etc, I would suggest you test it using classic State-based verification: create a proxy that uses your interceptor and verify that your log reflects what you expect.
This might seem like a bit more work, but it provides a really good example of how the interceptor works independently from other parts of your code-base. Other developers on your team benefit from this as they can reference this example as a learning tool.
public class TypeThatSupportsLogging : ILoggable
{
public ILogger { get; set; }
public virtual void MethodToIntercept()
{
}
public void MethodWithoutLogging()
{
}
}
public class TestLogger : ILogger
{
private StringBuilder _output;
public TestLogger()
{
_output = new StringBuilder();
}
public void DebugFormat(string message, params object[] args)
{
_output.AppendFormat(message, args);
}
public string Output
{
get { return _output.ToString(); }
}
}
[TestFixture]
public class LoggingWithDebugInterceptorTests
{
protected TypeThatSupportsLogging Input;
protected LoggingWithDebugInterceptor Subject;
protected ILogger Log;
[Setup]
public void Setup()
{
// create your interceptor
Subject = new LoggingWithDebugInterceptor();
// create your proxy
var generator = new Castle.DynamicProxy.ProxyGenerator();
Input = generator.CreateClassProxy<TypeThatSupportLogging>( Subject );
// setup the logger
Log = new TestLogger();
Input.Logger = Log;
}
[Test]
public void DemonstrateThatTheInterceptorLogsInformationAboutVirtualMethods()
{
// act
Input.MethodToIntercept();
// assert
StringAssert.Contains("MethodToIntercept", Log.Output);
}
[Test]
public void DemonstrateNonVirtualMethodsAreNotLogged()
{
// act
Input.MethodWithoutLogging();
// assert
Assert.AreEqual(String.Empty, Log.Output);
}
}
No methods? What are you testing?
Personally, this sounds like it goes too far. I realize that TDD and code coverage is dogma, but if you mock an interface with no methods and prove that the mocking framework does what you instructed it to do, what have you really proven?
There's another misdirection going on here: logging is the "hello world" of aspect oriented programming. Why aren't you doing logging in an interceptor/aspect? If you did it that way, there'd be no reason for all your classes to implement ILoggable; you could decorate them with logging capability declaratively. I think it's a less invasive design and a better use of interceptors.

Execute setup() once workaround causing TestSuit to fail

I have 2 files:
xxxxxTest.java
[refer this]
public class xxxxxTest extends TestCase {
// Run setup only once
public static Test suite() {
TestSetup setup = new TestSetup(new TestSuite(xxxxxTest.class)) {
protected void setUp() throws Exception {
//Some init which i need only once
}
protected void tearDown() throws Exception {
}
};
return setup;
}
public void testMyFirstMethodTest() {
assertNotNull(do stuff here);
}
}
AllTests.java
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("Test for xxxxxx");
//$JUnit-BEGIN$
suite.addTestSuite(xxxxxTest.class);
//$JUnit-END$
return suite;
}
}
So, my individual test(xxxxxTest.java) works fine, exactly as I want.When i run my test suite (AllTests.java), it fails, because the init in setup() i provided in xxxxxTest.java are not being executed.
Any suggestions?
UPDATE
I tried #BeforeClass in JUnit 4. But, it didn't help because in my ssetUp() method, I start an embedded Jetty server (server.start()), the server works fine with the code I posted, but when I do the same with #BeforeClass, it does not work.
In rare cases I also hacked around with static when using JUnit3.
In your case:
give the static{} initializer a try, maybe it works opposed to your static initialization.
if possible upgrade to JUnit4 and use #BeforeClass annotation (it is run once for a test-class). Your other JUnit3 test-classes should be runnable with JUnit4 test-runner also.
Similar to manuel's point: do you -need- to use JUnit 3? Then a class-level static{} initializer might be your best bet.
Otherwise, I recommend using JUnit 4, which has a construct which would might enjoy:
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class xxxxxTest {
#BeforeClass
public static void beforeClass() {
//Some init which i need only once
}
#Test
public void testMyFirstMethodTest() {
Assert.assertNotNull("");//do stuff here);
}
}