Spring Injection and Annotations - java

Have looked around a lot but am unable to figure out an approach or if it is even possible; here is the question, any directions/word of advice would be very helpful.
Is it possible to have a method annotation say, #TestAnnotation that could be used as follows?
#TestAnnotation(element="something" id="someId")
public void someMethod() {
AnObj anObj = id.getAnObj();
}
"someId" is a wrapper around "AnObj" class; 'id' is an instance of "someId". And whatever is passed to 'element' is to be accepted as a parameter or configuration element to be used in creating an instance of "someId" and assigning it to 'id'.
Thanks and regards

And Why dont simple use AOP and do all that you need in #Before method
http://www.journaldev.com/2583/spring-aop-example-tutorial-aspect-advice-pointcut-joinpoint-annotations-xml-configuration

Change it to this:
#TestAnnotation(element="something" id="someId")
public void someMethod(Object something, AnObj anObj) {
}
Then you can set up an aspect to intercept methods with that annotation and assign the necessary objects to the parameters of the method before calling.

Related

How to define AnswersWithDelay for a void returning method

So, I want to mimic in Mockito a method that is making a network call and is waiting for it to complete before returning. I found this nice answer here: https://stackoverflow.com/a/50530261/4433222 that suggests using AnswersWithDelay.
Issue is though that I struggle to define a method's behavior for a method that returns void. AnswersWithDelays constructor requires a parameter of Answer<Object> type, and I wasn't able to find how to set it as void. Any clues?
First of all, AnswersWithDelay is an internal class of Mockito. So you should not use it directly. Instances of this class are supposed to be created by using the factory methods in the public AdditionalAnswers class.
So all you need is
doAnswer(AdditionalAnswers.answersWithDelay(delay, invocation -> null)).when(mockObject).doSomething();
Based on this answer, with a draft test class.
#ExtendWith(SpringExtension.class)
public class MockDelayVoidTest {
#MockBean
private Object myMock;
void test(){
Mockito.doAnswer(AdditionalAnswers.answersWithDelay(1000, invocationOnMock -> {
//here you can customize the behavior of your mock method
return null;}))
.when(myMock).toString();
}
}
Another way may be,
Mockito.doAnswer(invocation -> {
TimeUnit.SECONDS.sleep(5);
return null;
}).when(mock).doSomething();

How to call a method with a parameter decorated with #Vaule annotation in a spring project?

When there is a parameter decorated with #Value annotaion in a method, it is ofcourse no compile error. Just like the code bellow:
public void Sample0(#Value("${hmac.key}") Optional<String> key) {
if (key.isPresent()) {
System.out.println(key.get());
} else {
System.out.println("can not find key");
}
}
My Question is how to call a function like this? I try to call it directory, but it failed. The calling function code bellow.
#Test
public void sampleTest0() {
JwtService.Sample0();
}
So anyone can tell me what's the right way to call the function? Thx.
I think another way of doing this is to save #Value as local variable and then use it into function.
I think you can use #Value in parameters only in constructors. Your Sample0 is not a constructor, just a regular method because it has a return type, i.e. void.
If you use #Value in constructor parameter, you can autowire Sample0 and spring will inject the value while instantiating it.
If you need to pass a value to a regular method instead, you can use #Value on a field in the calling class and then pass that field as an argument to this method in Sample0.

Is it possible to use JMockit's Deencapsulation API to exchange method implementation?

So, basically, a there is some poor code that I cannot change that needs to be tested. Traditionally, you inject your mocked dependencies, but with this code, I cannot do so, because there are no setter methods. Worse, the function I need to test calls a bunch of static factory methods-I can't just use the MockUp strategy to swap out the implementation there, because there is no class instance to be injected at all.
In C/++, you can retrieve a pointer to a function and know it's type by it's signature. If you changed the pointer, then you could potentially change how the stack was constructed by the compiler and you could pass function's around and all that Jazz.
Is there a way to use the Deencapsulation API to replace a static method implementation? Using this, I could write my own class, descend from the traditional, but return mocked objects in order that dependency injection still be achieved?
public class TestedClass {
public static void testedMethod() {
UnMockableType instanceVariable =
UnInjectableFactory.staticFactoryConstructor();
instanceVariable.preventControlFlowInfluenceThroughMocking();
}
}
Easy enough:
#Test
public void exampleTestUsingAMockUp()
{
new MockUp<UnMockableType>() {
#Mock
void preventControlFlowInfluenceThroughMocking() {}
};
TestedClass.testedMethod();
}
Above, UnInjectableFactory isn't mocked because it doesn't need to be (assuming it simply instantiates/recovers an UnMockableType).
It could also be done with #Mocked and the Expectations API.

Can I combine manual instantiation with autowiring?

Ok. I am not sure how to even ask the question, which is the sign I must be missing something. The best I can do is: "Is there a way to instantiate an object manually and still use injection within that object?"
Concretely, say I have:
class A {
public A(MyObject1 obj1, MyObject2 obj2, ..., MyObjectn objn) {
...
}
}
I want to wire all of these objects except MyObjectn. As far as I know, if I use #Autowired in front of that constructor above, then I should only instantiate that object as follows in the code that uses an instance of that class:
#Autowired
A a;
which doesn't allow me to pass in objn in the constructor manually. Is there a way to get around that limitation short of manually initializing A in the code that uses an instance of that class?
Short answer - no.
You either use an IoC or you manually instantiate Objects.
One workaround that comes to my mind:
Create a Service with every MyObject1 being #Autowired
create a method inside this service:
public A createA(MyObjectN objn) {
return new A(object1, object2... objn); //note that object1 .. objectn-1 are autowired.
}
Inject the service with #Autowired ;) and call service.createA()
sunilkumar from vmoksha
NO we cant create like that

EasyMock: Mock out a constructor call in java

I have a looked at similar questions on this board, but none of them answer my question. This sound strange, but is it possible to mock out a constructor call on the object you're mocking.
Example:
class RealGuy {
....
public void someMethod(Customer customer) {
Customer customer = new Customer(145);
}
}
class MyUnitTest() {
public Customer customerMock = createMock(Customer.class)
public void test1() {
//i can inject the mock object, but it's still calling the constuctor
realGuyobj.someMethod(customerMock);
//the constructor call for constructor makes database connections, and such.
}
}
How can I expect a constructor call? I can change the Customer constructor call to use newInstance, but im not sure if that will help. I have no control over what the body of the new Customer(145) constructor does.
Is this possible?
you can do so with EasyMock 3.0 and above.
Customer cust = createMockBuilder(Customer.class)
.withConstructor(int.class)
.withArgs(145)
.addMockedMethod("someMethod")
.createMock();
You can't do this with easymock, as it doesn't support mocking constructors. There's a library called powermock which can do that and is the only mocking library, as far as I know, that can stub constructors and static methods in Java.
import static org.powermock.api.easymock.PowerMock.expectNew;
instance = new UsesNewToInstantiateClass();
expectNew(AnyOldClass.class).andReturn(anyClass);
And this is why you want to inject your dependencies (via Guice or similar package) instead of creating them inside your class.
Then you don't HAVE TO mock their construction.
This assumes (a) that this is your code that you can change, and (b) that the objects in question are complex enough that you should inject them. Constructing simple objects inside your class are fine, but then you shouldn't need to mock them.

Categories

Resources