Spring AOP in different projects does not work - aop

I am new to Spring AOP and AspectJ but the simplicity they can provide makes me want to use them.
The questions is: I have two projects, one is a spring boot application server and the other one contains all the utilities functions core. I want to implement logging aspect in both projects and here is what I did:
server
#Aspect
#Component
public class MethodLoggingAspect {
#Around("#annotation(logExecutionTime)")
public Object methodLog(ProceedingJoinPoint joinPoint, LogExecutionTime logExecutionTime) throws Throwable {
final Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
final long start = System.nanoTime();
Object proceed = joinPoint.proceed();
final long end = System.nanoTime();
logger.info("method={}, millis={}", joinPoint.getSignature().toShortString(), TimeUnit.NANOSECONDS.toMillis(end - start));
return proceed;
}
}
#Configuration
#EnableAspectJAutoProxy
#ComponentScan
public class BeanConfiguration {
}
core
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface LogExecutionTime {
}
I use the annotation LogExecutionTime both in core and application server these are two different jars and server has dependency core. I expect the aspect will work in both two parts when I run server, but the fact is that only methods in server have the aspect weaved in.
I also tried to define the aspect in core and use aspectJ to do compile-time weaving. But there is Immutable library in core, which will throw a compile time error when I use aspectj-maven-plugin.
Can anyone help me with it? Thanks!

Related

How to use WebApplicationFactory in .net6 (without speakable entry point)

In ASP.NET Core 6 default template moves everything from Sturtup.cs into Program.cs, and uses top-level statements in Program.cs, so there's no more (speakable) Program class ether.
That looks awesome, but now, I need to test all of this. WebApplicationFactory<T> still expects me to pass entry-point-class, but I cannot do this (due to it's name now being unspeakable).
How integration tests are expected to be configured in ASP.NET Core 6?
Note that if you are trying to use xUnit and its IClassFixture<T> pattern, you will run into problems if you just use the InternalsVisibleTo approach. Specifically, you'll get something like this:
"Inconsistent accessibility: base class WebApplicationFactory<Program> is less accessible than class CustomWebApplicationFactory."
Of course you can solve this by making CustomWebApplicationFactory internal but it only moves the problem as now your unit test class will give the same error. When you try to change it there, you will find that xUnit requires that tests have a public constructor (not an internal one) and you'll be blocked.
The solution that avoids all of this and allows you to still use IClassFixture<Program> is to make the Program class public. You can obviously do this by getting rid of the magic no class version of Program.cs, but if you don't want to completely change that file you can just add this line:
public partial class Program { } // so you can reference it from tests
Of course once it's public you can use it from your test project and everything works.
As an aside, the reason why you typically want to prefer using IClassFixture is that it allows you to set up your WebApplicationFactory just once in the test class constructor, and grab an HttpClient instance from it that you can store as a field. This allows all of your tests to be shorter since they only need to reference the client instance, not the factory.
Example:
public class HomePage_Get : IClassFixture<CustomWebApplicationFactory>
{
private readonly HttpClient _client = new HttpClient();
public HomePage_Get(CustomWebApplicationFactory factory)
{
_client = factory.CreateClient();
}
[Fact]
public async Task IncludesWelcome()
{
HttpResponseMessage response = await _client.GetAsync("/");
response.EnsureSuccessStatusCode();
string stringResponse = await response.Content.ReadAsStringAsync();
Assert.Contains("Welcome.", stringResponse);
}
}
Finally note that Damian Edwards' MinimalAPIPlayground was updated to use this approach after we discussed the issue. See this commit
The problem is was solved on ASP.NET Core RC1, but as of now (September 20, 2021) the docs are incomplete.
The compiler generates a Program class behind the scenes that can be used with WebApplicationFactory<>. The class isn't public though so the InternalsVisibleTo project setting should be used.
Damien Edwards' Minimal API sample uses the latest nightly bits. The test web app class is declared as :
internal class PlaygroundApplication : WebApplicationFactory<Program>
{
private readonly string _environment;
public PlaygroundApplication(string environment = "Development")
{
_environment = environment;
}
protected override IHost CreateHost(IHostBuilder builder)
{
...
In the application project file,InternalsVisibleTo is used to make the Program class visible to the test project:
<ItemGroup>
<InternalsVisibleTo Include="MinimalApiPlayground.Tests" />
</ItemGroup>
RC1 is feature complete and, judging by previous major versions, it will probably be the first version to have a Go Live license, which means it's supported in production.
I tried
<InternalsVisibleTo Include="MinimalApiPlayground.Tests" />
but no cigar! Removed it and added a partial class to program.cs
#pragma warning disable CA1050 // Declare types in namespaces
public partial class Program
{
}
#pragma warning restore CA1050 // Declare types in namespaces
amazingly it worked.

Can we access spring bean in Karate feature?

I have a class like below, can I access the myServer object or call handleOperation() method (which can use the injected bean) in Karate Feature file? If yes then may I know how?
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {MyApiApp.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ContextConfiguration(classes = {AcceptanceTestConfiguration.class})
#ActiveProfiles("test")
#KarateOptions(features = "classpath:acceptanceTest/api/myapi.feature", tags = "#myapi")
public class MyAtddTest {
#Autowired
private MyServer myServer;
public void handleOperation() throws Exception {
myServer.handle();
}
}
There is no direct support for spring or the annotations. And not sure if you can mix the test annotations.
But take a look at the Spring MVC Dispatcher example here: https://github.com/intuit/karate/tree/master/karate-mock-servlet#mocking-your-servlet
Specifically how using Java interop you can do anything you want. I recommend getting the spring context using first-principles. For e.g:
ApplicationContext context = new AnnotationConfigApplicationContext(AcceptanceTestConfiguration.class);
And then getting beans out of it. Setting a test profile via System.setProperty() should be simple, search for it. You can do all this in even the karate-config.js and then it should be easy to use from all Scenario-s.
EDIT - also refer: https://github.com/Sdaas/hello-karate

Dropwizard Integrated Testing with Mocks for DB

First: Yes I read this https://dropwizard.github.io/dropwizard/manual/testing.html
I want to do some integration testing and tahts why I have to start the entire application. Now the problem is, that I have some interfaces to the "outside world" like DB or one internal Rest-Client, who speaks with one remote app. I want to mock them with mockito. Normally thats no problem.
Now my question: How can I start entire application with mocked DB and mocked client?
The problem at the moment is, that I get this DB connection and client from my configuration class via getDBClient() ... and I'm not willing to build in some test code in my config, because its production code. So if I start the entire app via DropwizardAppRule, the app tries to connect to database, but in testing enviroment, there is no DB available.
Is there a easy way to say: Start my app but if you call DB or client, then use this XY mock?
What I tried yet:
One new class "ExtendedService extends Service extends Application" and one "ExtServiceConfiguration extends ServiceConfiguration", but without any success. But I having trouble if I override some methods in the config class returning the mock. It does not fit all together.
At the moment I read the docs for mockito spy, perhaps this can help, but I'm not sure how to use this in the DW integrated tests. I now try to mock 2 of my configuration class methods to return a DB and client mock. Perhaps someone can help me, how to mock the TestConfiguration in the next example code:
#ClassRule
public static final DropwizardAppRule<TestConfiguration> RULE =
new DropwizardAppRule<TestConfiguration>(MyApp.class, resourceFilePath("my-app-config.yaml"));
EDIT:
#ClassRule
public static final DropwizardAppRule RULE = new DropwizardAppRule(.....)
In #BeforeClass I do the following:
ServiceConfiguration oldConfig = RULE.getConfiguration();
ServiceConfiguration spy = Mockito.spy(oldConfig);
//Then DB mocking
IDatabaseLayer dBMock = mock(IDatabaseLayer.class);
Mockito.when(dBMock.isConnected()).thenReturn(true);
... // other mocking functions for DB
//this is important, it say, that the mocked config class should use the mocked DB
Mockito.doReturn(dBMock).when(spy).getDataBaseLayer(); // my configuration class has this method, so mocking config class with last created dbMock
// do other mockings if needed
Thats all I had done to start entire application.
If you really want to run an integration test, I suggest using a memory or temporary database like h2 or sqlite, if you can, by creating a new yml file with the relevant settings; and use a mocked http service such as Wiremock.
Otherwise stick to ResourceTestRules as th3morg suggests.
If you want to mock specific things but still keep the whole flow of dropwizard, then you need to manage your own Application instance and make it possible to inject your dependencies to your Application class. Because DropwizardAppRule doesn't give you that flexibility.
Example: You want to be able to override the dependencies on your application class.
public class MyApplication extends Application {
private FooManager fooManager;
// Need to leave an empty constructor for other uses
public MyApplication(){
}
public MyApplication(FooManager fooManager){
this.fooManager = fooManager;
}
#Override
public void run(Configuration configuration, Environment environment) throws Exception {
if(fooManager == null){
fooManager = new FooManagerImpl();
}
// stuff
}
}
Then on your test, you create your own instance (or you can create a rule class by copying and modifying DropwizardAppRule source code. Edit: Looks like you can inherit DropwizardTestSupport class and override public Application<C> newApplication().).
#Test
public void test(){
FooManager fooManager = mock(FooManager.class);
MyApplication myApplication = new MyApplication(fooManager);
myApplication.run("server", "config.yml");
}
I think that you should be using io.dropwizard.testing.junit.ResourceTestRule instead, which is used for testing Jersey resources (i.e. making calls to your REST API endpoints). The DropwizardAppRule will start the whole application and stop it at the end of your test. That class seems to be intended for end-to-end testing in which you would not do any mocking whatsoever.

wicket and AtUnit

I've started playing with Wicket and I've chosen Guice as dependency injection framework. Now I'm trying to learn how to write a unit test for a WebPage object.
I googled a bit and I've found this post but it mentioned AtUnit so I decided to give it a try.
My WebPage class looks like this
public class MyWebPage extends WebPage
{
#Inject MyService service;
public MyWebPage()
{
//here I build my components and use injected object.
service.get(id);
....
}
}
I created mock to replace any production MyServiceImpl with it and I guess that Guice in hand with AtUnit should inject it.
Now the problems are:
AtUnit expects that I mark target object with #Unit - that is all right as I can pass already created object to WicketTester
#Unit MyWebPage page = new MyWebPage();
wicketTester.startPage(page);
but usually I would call startPage with class name.
I think AtUnit expects as well that a target object is market with #Inject so AtUnit can create and manage it - but I get an org.apache.wicket.WicketRuntimeException: There is no application attached to current thread main. Can I instruct AtUnit to use application from wicketTester?
Because I don't use #Inject at MyWebPage (I think) all object that should be injected by Guice are null (in my example the service reference is null)
I really can't find anything about AtUnit inside Wicket environment. Am I doing something wrong, am I missing something?
I don't know AtUnit but I use wicket with guice and TestNG. I imagine that AtUnit should work the same way. The important point is the creation of the web application with the use of guice.
Here how I bind all this stuff together for my tests.
I have an abstract base class for all my tests:
public abstract class TesterWicket<T extends Component> {
#BeforeClass
public void buildMockedTester() {
System.out.println("TesterWww.buildMockedTester");
injector = Guice.createInjector(buildModules());
CoachWebApplicationFactory instance =
injector.getInstance(CoachWebApplicationFactory.class);
WebApplication application = instance.buildWebApplication();
tester = new WicketTester(application);
}
protected abstract List<Module> buildModules();
The initialization is done for every test class. The subclass defines the necessary modules for the test in the buildModules method.
In my IWebApplicationFactory I add the GuiceComponentInjector. That way, after all component instantiation, the fields annotated with #Inject are filled by Guice:
public class CoachWebApplicationFactory implements IWebApplicationFactory {
private static Logger LOG = LoggerFactory.getLogger(CoachWebApplicationFactory.class);
private final Injector injector;
#Inject
public CoachWebApplicationFactory(Injector injector) {
this.injector = injector;
}
public WebApplication createApplication(WicketFilter filter) {
WebApplication app = injector.getInstance(WebApplication.class);
Application.set(app);
app.addComponentInstantiationListener(new GuiceComponentInjector(app, injector));
return app;
}
}

Late binding with Ninject

I'm working on a framework extension which handles dynamic injection using Ninject as the IoC container, but I'm having some trouble trying to work out how to achieve this.
The expectation of my framework is that you'll pass in the IModule(s) so it can easily be used in MVC, WebForms, etc. So I have the class structured like this:
public class NinjectFactory : IFactory, IDisposable {
readonly IKernel kernel;
public NinjectFactory(IModule[] modules) {
kernel = new StandardKernel(modules);
}
}
This is fine, I can create an instance in a Unit Test and pass in a basic implementation of IModule (using the build in InlineModule which seems to be recommended for testing).
The problem is that it's not until runtime that I know the type(s) I need to inject, and they are requested through the framework I'm extending, in a method like this:
public IInterface Create(Type neededType) {
}
And here's where I'm stumped, I'm not sure the best way to check->create (if required)->return, I have this so far:
public IInterface Create(Type neededType) {
if(!kernel.Components.Has(neededType)) {
kernel.Components.Connect(neededType, new StandardBindingFactory());
}
}
This adds it to the components collection, but I can't work out if it's created an instance or how I create an instance and pass in arguments for the .ctor.
Am I going about this the right way, or is Ninject not even meant to be be used that way?
Unless you want to alter or extend the internals of Ninject, you don't need to add anything to the Components collection on the kernel. To determine if a binding is available for a type, you can do something like this:
Type neededType = ...;
IKernel kernel = ...;
var registry = kernel.Components.Get<IBindingRegistry>();
if (registry.Has(neededType)) {
// Ninject can activate the type
}
Very very late answer but Microsoft.Practices.Unity allows Late Binding via App.Config
Just in case someone comes across this question