mock autowired field in#Import class - spring

I am doning an unit test which require some objects which injected by spring so I use:
#RunWith(SpringRunner.class)
#Import({BConfig.class})
public class ATest {
private A a;
#Autowired
private B b;
#Before
public void init() {
a = new A(b);
}
}
However, the BConfig class has an autowired field c which I don' need in this test:
class BConfig {
#Autowired
C c;
#Bean
public getB() {
return new B();
}
// other method code will use field c
}
The autowired c field will get data from redis in #PostConstruct which don't exist in unit test. If I don't omit that, the unit test will report error due to redis data is not exist.
I have a solution to make C to 2 subclasses CProduction and CUnitTest both of them implements interface C, then active profile to use CUnitTest in unit test. However this is some kind of invasive because if don't do the unit test, the interface of C is useless.
Is there a better way to do this?

Consider using:
#RunWith(SpringRunner.class)
#ContextConfiguration({BConfig.class})
class ATest {
#MockBean // will place a mock implementation of C to the context instead of real one that tries to connect with Redis.
C c;
...
}
Note that it will work seamlessly if C is an Interface. Otherwise it will try to create a proxy by inheritance (something that extends from C) and if C has some redis-related code in constructor it might still attempt to call it.
Update 1
Based on OP's comment in an attempt to clarify the answer:
When spring application context starts it basically resolves all the beans and injects what's needed.
First it resolves the bean definitions (metadata) - the real class, scope, etc.
And then it creates beans in the order that will allow injection. For example, it class A has a field of class B (both are beans) then spring must create B first, then create a and inject B into A.
Now, #MockBean is a hook relevant for tests. It tells spring application context used in test that instead of a regular bean definition that spring is able to parse out of #Configuration classes or find the component due to #Component annotation placed on it, it should use the Mock - something that is generated in runtime with frameworks like Mockito.
This mock implementation can later be used to specify the expectations (see Mockito basic tutorial, there are plenty of those on internet), but what's more important for your case, it wont connect to redis because this mock implementation doesn't have any redis related code.
Update 2
The configuration should be rewritten as follows:
#Configuration
public class BConfig {
#Bean
public getB() {
return new B();
}
#Bean
public C c() {
return new C();
}
// other method code will use field c:
// if for example D uses C: then you can:
#Bean
public D d(C c) {
return new D(c);
}
}

Related

Spring transaction creation

This question was asked me in one interview
class A{
#Transactional
public void test1(){
test2();
}
#Transactional(propagation = REQUIRED.NEW)
public void test2(){}
}
class B extends A{
public void test1(){
super.test1();
}
}
He asked me how many transaction objects would be created? The answer was 1, not 2. now I am having a hard time struggling with this part. He said this is how CgLib proxy works, can anyone explain this part?
This program can be rewritten like:
class A{
#Transactional
public void test1(){
this.test2(); // this is added
}
#Transactional(propagation = REQUIRED.NEW)
public void test2(){}
class B extends A{
public void test1(){
super.test1();
}
suppose you get A from application context and call the test1() method on that:
var a = context.getBean(A.class);
a.test1()
we know that a is actually the proxy object so a transaction is going to be created. in test1() method we call this.test2() method.
From Spring doc:
However, once the call has finally reached the target object any
method calls that it may make on itself, such as this.bar() or
this.foo(), are going to be invoked against the this reference, and
not the proxy
so for test2() method no transaction is going to be created because this is invoked against the A class not the proxy class with all transactional stuff support.
Now suppose that you get B from application context and invoke test1() method against it.
var b = context.getBean(B.class);
b.test1()
Because B is the subclass of A and A is annotated with Transactional, B itself is a proxy (#Transactional is automatically inherited even though test1() in B is not annotated with #Transactional). so a transaction is going to be created. when we reach the target object all transaction stuff goes away and no more transaction is going to be created like the first case.

How to pass dynamic values to a constructor from another class which is injected as autowired object

How to pass dynamic values to a constructor from another class which is injected as autowired object?
#Service
Class Test {
int a;
String b;
public Test(int a, String b) {
this.a = a;
this.b = b;
}
}
Class Sample {
#Autowired
Test test;
}
How can I pass values to Test class constructor from Sample class?
Spring beans are immutable by idea.
If your Test instance is different for every instance of Sample class, it don't have to be a spring bean, especially if some fileds on the Test instance depend on values from the Sample instance.
Maybe a solution would be to change your Test class scope so you can create multiple instances, but you have to explain more what you mean by dynamic values.

Spring framework and java like Object collectors In Scala

In Spring framework and Java world, there is an interesting object collector pattern that I use.
For example consider below -
public interface Calculator {
SomeOutput calculate(SomeInput input);
}
#Component
public class CalImpl1 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
#Component
public class CalImpl2 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
Now this can easily injected in another class using Spring DI
#Component
public class Main {
//This line collects all to implementors of this and set it here.
#Autowired
public List<Calculator> calculators;
//other methods
}
Now problem is I am not sure how same thing can be achieved in scala. I have done some search and found cake pattern (http://loicdescotte.github.io/posts/scala-di/) used in scala but that didn't seem to achieve same thing as object collectors like above. I also want to follow open close principle which I think gets violated in cake pattern but using object collectors I can easily achieve it.
is there a way achieve same object collectors like implementation in scala?
There are templates in lighbend activator that illustration using spring DI on Play, Akka and Scala applications. Please see this: https://www.lightbend.com/activator/templates#filter:spring
I haven't used Spring as DI, I usually use Guice (explicitly used because it's default on play framework 2) and Implicits parameters both as a compilation DI.
Sample:
class B
class X(x: Int)(implicit c: B)
//DI - mostly define in main method/application
implicit val c: B = new B
val x = new X(2)
Explicitly using java.util.List worked for me. This is not the prettiest solution but it shows that it basically works. Haven't tried that but implementing a corresponding PropertyEditor you could stick with the Scala types.
trait Calculator {
def calculate(input: SomeInput) : SomeOutput
}
#Component
class CalImpl1 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class CalImpl2 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class Main #Autowired()(calculators: java.util.List[Calculator]) {
// or inject field if constructor injection is not desired
// #Autowired
// var calculators: java.util.List[Calculator] = _
}
object Main {
def main(args: Array[String]) = {
val ctx = new AnnotationConfigApplicationContext("your package name here")
val main = ctx.getBean(classOf[Main])
// calculators should now be wired in the returned instance
}
}

Unit testing with Mockito

I am writing unit tests for service layer in my spring application.
Here is my service class
#Service
public class StubRequestService implements RequestService {
#Autowired
private RequestDao requestDao;
#Transactional(propagation = Propagation.REQUIRED, readOnly = true)
#Override
public Request getRequest(Long RequestId) {
Request dataRequest = requestDao.find(requestId);
return dataRequest;
}
}
Here is my test class
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" })
public class StubRequestServiceTest {
#Mock
public RequestDao requestDao;
StubRequestService stubRequestService; // How can we Autowire this ?
#org.junit.Before
public void init() {
stubRequestService = new StubRequestService(); // to avoid this
stubRequestService.setRequestDao(dataRequestDao);
// Is it necessary to explicitly set all autowired elements ?
// If I comment/remove above setter then I get nullPointerException
}
#Test
public void testGetRequest() {
Request request = new Request();
request.setPatientCnt("3");
when(requestDao.find(anyLong())).thenReturn(request);
assertEquals(stubRequestService.getRequest(1234L).getPatientCnt(),3);
}
}
Its working fine but I have few questions
How can we Autowire service class in test ? I am using constructor in init() method to create service object.
Do we have to set all Autowire element for service class ? For ex StubRequestService have autowired RequestDao which I need to set explicitly before calling test method otherwise it giveds nullPointerException as requestDao is null in StubRequestService.getRequest method.
Which are the good practices to follow while unit testing Spring service layer ? (If I am doing anything wrong).
Your test is fine. It doesn't even have to have the #ContextConfiguration annotation.
The whole point of dependency injection frameworks like Spring is to be able to unit test services by simply instantiating them, setting mock dependencies, and then call their methods.
You're doing it correctly. You don't need to have a Spring context for such unit tests. That's why they're called unit tests: they test it in isolation of all their actual dependencies, Spring included.
Side note: assuming you're using JUnit, the arguments of the assertXxx method should be swapped. The expected value comes before the actual value. It becomes important when the assertion fails and you have a message like "expecting 6 but was 3" rather than "expecting 3 but was 6".
If you really feel that it will make your tests easier to understand - you can initialize a spring context and fetch all of the objects from there. However, usually it will require creating a separate spring configuration XML file specifically for tests therefore I would not recommend it.
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testApplicationContext.xml");
stubRequestService = (RequestService)applicationContext.getBean("myRequestServiceBean");
(and 3) Basically, I prefer testing each component of my application in total isolation from eachother and that's why I do not recommend what I described in [1].
What that means, is you take a separate logical slice of your application and test only it, while fully mocking up everything it tries to access.
Let's say you have three classes:
//Fetches stuff from some webservice and converts to your app domain POJOs
class DataAccessLayer {
public void setWebservice(Webservice ws) {...};
public MyObject getMyObject() {...};
}
//Formats the domain POJOs and sends them to some kind of outputstream or stuff.
class ViewLayer {
public void setOutputStream(OutputStream os) {...};
public void viewMyObject(MyObject mo) {...};
}
//Main entry point of our MyObject fetch-process-display workflow
class Controller {
public void setDataAccessLayer(DataAccessLayer dal) {...};
public void setViewLayer(ViewLayer vl) {...};
public void showMyObject() {
MyObject mo = dal.getMyObject();
...some processing here maybe...
vl.viewMyObject(mo);
}
}
Now, what tests can we write here?
Test if DataAccessLayer properly converts the object from mocked up WS to our domain object.
Test if ViewLayer properly formats the object given to him and writes it to mocked up output stream.
Test if Controller takes an object from mocked up DataAccessLayer processes it properly and sends it to mocked up ViewLayer.
Or You can use springockito
https://bitbucket.org/kubek2k/springockito/wiki/Home, it will make your tests cleaner

How to wire them together by Spring annotations

I got a web application, and I have to wire it's components (A,B,C) together instead of direct method calls.
So, I dont know how can I wire object instances together when they need additional instances in the constructor.
I think in thats why the we can use (bean ... constructor-args ...) in application context.
But I dont know what if I want to use annotations.
I made a simple example to demostrate the concrete problem
class A
{
protected B b;
...
public func1(){
obj0 = makeObj0();
b = new B(obj0)
}
public Obj0 makeObj0() {...}
}
class B extends C
{
protected Obj0 obj0;
public B(Obj0 obj0){
super(obj0, "foo", new Obj1); //there is no another way to construct B, C
setObj0(obj0);
}
public void setObj0(obj){ obj0=obj;}
}
What is the best way to wiring A,B,(C) together (by annotations) because B, C needs additinal arguments right in their constructor.
Sorry for the lenghty explanation, and thanks for the tips in advance.
Cs
#Autowired
public B(..) {..}
will autowire all arguments. If you need additional arguments - then don't use constructor injection. Use setter/field injection. Provide an empty constructor and have #Autowired on each field that you need.
Hmm.. if you try with #Resource when initiating the B-class.
class A
{
#Resource(name = "b")
protected B b;
...
public func1(){
obj0 = makeObj0();
b = new B(obj0)
}
public Obj0 makeObj0() {...}
}
Then if you need to Autowire in B or C I find hard to tell.

Resources