I'm using get_it for IoC. However, my app throws an exception when I try to register a bean using an async call.
The function that throws the exception:
import 'package:elpee/service/localstorage_service.dart';
import 'package:get_it/get_it.dart';
GetIt locator = GetIt();
Future setupLocator() async {
LocalStorageService.getInstance().then((storageService) {
locator.registerSingleton(storageService);
});
}
The error:
Exception: Object of type LocalStorageService is not registered inside GetIt
If anyone could help me out, I'd greatly appreciate it :-)
You are trying to use get_it wrong way. Check to documentation.
First of all - get_it is Singleton, therefore don't use constructor, but
GetIt locator = GetIt.instance;
Second - implement LocalStorageService as a plain class and let the get_it to provide it as a Singleton:
void main()
...
void setupLocator() {
locator.registerLazySingleton(LocalStorageService());
}
}
To use full power of IoC define interface / abstract class definition for your storageservice and provide implementation of the interface.
void setupLocator() {
locator.registerLazySingleton<IStorageService>(LocalStorageService());
}
Related
I have following code which uses functional style to define two functions for kafka topics
#Bean
public Function<KStream<String, CloudEvent<ClassA>>, KStream<String, CloudEvent<ClassB>>> method1() {
....... //lambda
}
#Bean
public Function<KStream<String, CloudEvent<ClassB>>, KStream<String, CloudEvent<ClassC>>> method2() {
...... //lambda
}
For these two functions I define serdes so
#Bean
public Serde<CloudEventMessage<ClassA>> classASerde(ObjectMapper mapper, Validator validator) {
return StreamsSerdes.classASerde(mapper,validator);
}
#Bean
public Serde<CloudEventMessage<ClassB>> classBSerde(ObjectMapper mapper, Validator validator) {
return StreamsSerdes.classBSerde(mapper,validator);
}
This construction doesn't work as at runtime spring tries to deserialize CloudEvent<ClassB> with Serde of CloutEvent<ClassA>. Is there someway to give hint to use the correct serde for method1 and method2 ?
Secondly I could bypass the above issues by mentioning Serdes in application.properties
spring.application.cloud.stream.kafka.streams.bindings.method1-in-0.consumer.valueSerde=package.serde.StreamsSerdes$ClassASerde
spring.application.cloud.stream.kafka.streams.bindings.method2-in-0.consumer.valueSerde=package.serde.StreamsSerdes$ClassBSerde
However now I get other issues as these Serde classes don't have default constructor. I do need ObjectMapper, Validator from Spring to inject beans (#Service) to perfrom converstions/validations during deserialization.
Has anyone come across similar issues or perhaps have ideas how to resolve them ?
Thanks
I think it is a gap that the nested generics are not working right now in the binder. Do you mind creating an issue in the repository and linking this thread?
As to the second issue that you are running into when providing properties in application.properties, you can try using a workaround. The Serde interface has a configure method that takes a map.
default void configure(Map<String, ?> configs, boolean isKey) {
// intentionally left blank
}
Override this method in your Serde implementation and set those bean objects under some keys.
ObjectMapper mapper;
Validator validator;
#Override
public void configure(Map<String, ?> configs, boolean isKey) {
this.mapper = (ObjectMapper) configs.get("mapper.key");
this.validator = (Validator) configs.get("validator.key");
}
You need to remove accessing them from the constructor and use those fields directly for deserialization and serialization.
Then you provide this bean in your application to populate the map:
#Bean
public StreamsBuilderFactoryBeanCustomizer streamsBuilderFactoryBeanCustomizer(ObjectMapper mapper, Validator validator) {
return factoryBean -> {
factoryBean.getStreamsConfiguration().put("mappeer.key", mapper);
factoryBean.getStreamsConfiguration().put("validator.key", validator);
};
}
I haven't tried this code in an application, but it is something that you can try and see if it works with your code.
I came across an interesting article: AOP Aspects as mocks in JUnit
Since I have requirement to mock multiple final and private static variables, I am planning to use AOP in place of reflection or PowerMockito as they are causing issues with SpringJUnit4ClassRunner.
Is there any way I can use #Aspect for test classes without using the annotation #EnableAspectJAutoProxy? (I want to use an aspect targeting class X only in one test case.)
This is a sample of what I want to do.
The question is answered(adding for discussion on what could be done)
//External class
public final class ABC(){
public void method1() throws Exception {}
}
#Service
public void DestClass() {
private static final ABC abc = new ABC();
public Object m() {
// code (...)
try {
abc.method1();
}
catch(Exception e) {
// do something (...)
return null;
}
// more code (...)
}
}
Spring framework allows to programmatically create proxies that advise target objects , without configuring through #EnableAspectJAutoProxy or <aop:aspectj-autoproxy>
Details can be found in the documentation section : Programmatic Creation of #AspectJ Proxies and the implementation is pretty simple.
Example code from the documentation.
// create a factory that can generate a proxy for the given target object
AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);
// add an aspect, the class must be an #AspectJ aspect
// you can call this as many times as you need with different aspects
factory.addAspect(SecurityManager.class);
// you can also add existing aspect instances, the type of the object supplied must be an #AspectJ aspect
factory.addAspect(usageTracker);
// now get the proxy object...
MyInterfaceType proxy = factory.getProxy();
Please note that with Spring AOP , only method executions can be adviced. Excerpt from the documentation
Spring AOP currently supports only method execution join points
(advising the execution of methods on Spring beans). Field
interception is not implemented, although support for field
interception could be added without breaking the core Spring AOP APIs.
If you need to advise field access and update join points, consider a
language such as AspectJ.
The document shared with the question is about aspectj and without providing the sample code to be adviced it is hard to conclude if the requriement can acheived through Spring AOP. The document mentions this as well.
One example of the integration of AspectJ is the Spring framework,
which now can use the AspectJ pointcut language in its own AOP
implementation. Spring’s implementation is not specifically targeted
as a test solution.
Hope this helps.
--- Update : A test case without using AOP ---
Consider the external Class
public class ABCImpl implements ABC{
#Override
public void method1(String example) {
System.out.println("ABC method 1 called :"+example);
}
}
And the DestClass
#Service
public class DestClass {
private static final ABC service = new ABCImpl();
protected ABC abc() throws Exception{
System.out.println("DestClass.abc() called");
return service;
}
public Object m() {
Object obj = new Object();
try {
abc().method1("test");
} catch (Exception e) {
System.out.println("Exception : "+ e.getMessage());
return null;
}
return obj;
}
}
Following test class autowires the DestClass bean with overridden logic to throw exception . This code can be modified to adapt to your requirement.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { DestClassSpringTest.TestConfiguration.class })
public class DestClassSpringTest {
#Configuration
static class TestConfiguration {
#Bean
public DestClass destClass() {
return new DestClass() {
protected ABC abc() throws Exception {
// super.abc(); // not required . added to demo the parent method call
throw new Exception("Custom exception thrown");
}
};
}
}
#Autowired
DestClass cut;
#Test
public void test() {
Object obj = cut.m();
assertNull(obj);
}
}
Following will be the output log
DestClass.abc() called // this will not happen if the parent method call is commented in DestClassSpringTest.TestConfiguration
Exception : Custom exception thrown
The article you are referring to is using full AspectJ, not Spring AOP. Thus, you do not need any #EnableAspectJAutoProxy for that, just
either the AspectJ load-time weaver on the command line when running your test via -javaagent:/path/to/aspectjweaver.jar
or the AspectJ compiler activated when compiling your tests (easily done via AspectJ Maven plugin if you use Maven)
Both approaches are completely independent of Spring, will work in any project and even when using Spring also work when targeting execution of third party code because no dynamic proxies are needed unlike in Spring AOP. So there is no need to make the target code into a Spring bean or to create a wrapper method in your application class for it. When using compile-time weaving you can even avoid weaving into the third party library by using call() instead of execution() pointcut. Spring AOP only knows execution(), AspectJ is more powerful.
By the way: Unfortunately both your question and your comment about the solution you found are somewhat fuzzy and I do not fully understand your requirement. E.g. you talked about mocking final and private static variables, which would also be possible in other ways with AspectJ by using set() and/or get() pointcuts. But actually it seems you do not need to mock the field contents, just stub the results of method calls upon the objects assigned to those fields.
Picocli has to introspect the command tree. Doing so it needs to load the domain object classes for every Command which slows down the jvm startup.
What options are there to avoid this startup lag? One solution I've come up with is described in https://github.com/remkop/picocli/issues/482:
I am using reflection to postpone any class loading until after the command is selected. This way only the command classes themselves are loaded and finally the classes which implement the single command requested by the user:
abstract class BaseCommand implements Runnable {
interface CommandExecutor {
Object doExecute() throws Exception;
}
// find the CommandExecutor declared at the BaseCommand subclass.
protected Object executeReflectively() throws Exception {
Class<?> innerClass = getExecutorInnerClass();
Constructor<?> ctor = innerClass.getDeclaredConstructor(getClass());
CommandExecutor exec = (CommandExecutor) ctor.newInstance(this);
return exec.doExecute();
}
private Class<?> getExecutorInnerClass() throws ClassNotFoundException {
return getClass().getClassLoader().loadClass(getClass().getName() + "$Executor");
}
public void run() {
try {
executeReflectively();
} catch(...){
/// usual stuff
}
}
}
A concrete commend class:
#Command(...)
final class CopyProfile extends BaseCommand {
#Option String source;
#Option String dest;
// class must NOT be static and must be called "Executor"
public class Executor implements CommandExecutor {
#Override
public Object doExecute() throws Exception {
// you can basically wrap your original run() with this boilerplate
// all the CopyProfile's field are in scope!
FileUtils.copy(source, dest);
}
}
}
It seems like https://github.com/remkop/picocli/issues/500 may provide the ultimate solution to this. What are the other options until then?
UPDATE February 2020:
Upgrading to a recent version of picocli should fix this issue.
From the picocli 4.2.0 release notes:
From this release, subcommands are not instantiated until they are matched on the command line. This should improve the startup time for applications with subcommands that do a lot of initialization when they are instantiated.
An alternative that doesn’t require any code changes is to use GraalVM to compile your picocli-based application to a native image.
This article shows how to do this and the resulting startup time is 3 milliseconds.
I was trying to verify whether my log warning message is written via NUnit mocking. I am getting this error message :
An exception of type 'System.NotSupportedException' occurred in Moq.dll but was not handled in user code
Additional information: Invalid verify on a non-virtual (overridable in VB) member: m => m.LogWarning(String.Format("comments not found for part number :{0}", (Object)0), new[] { "111" })
code:
mockLogger.Verify(m => m.LogWarning($"comments not found for part number :{0}", "111"), Times.Exactly(1));
This is happening because NUnit mocking framework does not support extension methods. A few people on stack overflow have suggested to use Log method instead of level wise methods.
What am I missing?
Firstly, you don't need the $ at the start of the string. That's for string interpolation. The LogWarning message is doing a string.format, hence the {0}
Mock frameworks cannot directly mock static methods. The problem in your case is the LogWarning method - that is the static (extension) method.
The simplest way of overcoming this issue is by using a wrapper class. Here's how I got it, in your case.
Firstly I created an interface
public interface IMyLogWarning
{
void LogWarning(string msg, params object[] args);
}
Then I created a class which implements that interface
public class MyLogWarning<T> : IMyLogWarning where T : class
{
private readonly ILogger _logger;
public MyLogWarning(ILogger<T> logger)
{
// Using constructor for DI
_logger = logger;
}
public void LogWarning(string msg, params object[] args)
{
_logger.LogWarning(msg, args);
}
}
The reason for these two is that I'll use these in my code as well as the unit test.
The constructor in the class is setup so it can be populated using dependency injection, something like this in your ConfigureServices method. Feel free to change this; was a quick stab at it on my part.
services.AddTransient<IMyLogWarning, MyLogWarning<MyViewModel>>();
You can then create a unit test that's roughly like this
[Test]
public void LoggingTest_LogAMessage_ConfirmedLogWasRun()
{
// TODO - add the rest of your test code
// Arrange
var warningMsg = "comments not found for part number :{0}";
var partNumber = "111";
var mockLogger = new Mock<IMyLogWarning>();
// Act
mockLogger.Object.LogWarning(warningMsg, partNumber);
// Assert
mockLogger.Verify(m => m.LogWarning(warningMsg, partNumber), Times.Exactly(1));
}
public Product GetbyID(int id)
{
try
{
//mycode Product p=..........
}
catch (DataAccessException ex)
{
throw new BusinessException(ex.ErrorCode);
}
catch (Exception ex)
{
BusinessExceptionHandler.LogException(ex);
}
return p;
}
Given above is a code snippet that i need to write test cases.
here LogException(ex); is a static method in static class BusinessExceptionHandler
I have reference to Moq frame work 2.6.1014.1
How can I Moq the method BusinessExceptionHandler.LogException
I do prefer a mocking mechanism that don't need any change in method GetbyID
Moq doesn't allow the mocking of static methods so you will probably need to change the working of the static method. One option is to have the static method call an instance method of a dependency. So you'll create a "Logger" class with a Log method and add a static Logger field / property (BusinessExceptionHandler.Logger) to your static class. In the real-world scenario you can populate BusinessExceptionHandler.Logger with a standard Logger instance, using it as a Singleton. For testing, inject a Mock into the BusinessExceptionHandler.Logger and set up your expectations and verify against the mock.
Moq (and NMock, RhinoMock) will not help you here. You will have to create a wrapper class ( and virtual method ) around the LogException and use it in production code and test using that.
Or you can use a tool like TypeMock, Microsoft.Fakes etc ( http://stacktoheap.com/blog/2012/11/11/testing-extension-methods-with-microsoft-fakes/ ) if you absolutely cannot change your existing code.
Here is how I get around the problem. Say this is the class you want to unit-test:
public static class TaskFactory
{
public static T CreateTask<T>(long workRequestId, ProcessTriggerType workRequestType)
{
var task = some code to do the work;
return (T)task;
}
}
Create an interface and a wrapper class implementing it:
public interface ITaskFactoryFacade
{
T CreateTask<T>(long workRequestId, ProcessTriggerType workRequestType);
}
public class TaskFactoryFacade : ITaskFactoryFacade
{
public T CreateTask<T>(long workRequestId, ProcessTriggerType workRequestType)
{
return TaskFactory.CreateTask<T>(workRequestId, workRequestType);
}
}
Now mock out this class:
var taskFactoryFacadeMock = new Mock<ITaskFactoryFacade>();
taskFactoryFacadeMock.Setup(t => t.CreateTask<SomeTask>(It.IsAny<long>(), It.IsAny<SomeType>())).Returns(new SomeTask());
Happy Moqing.