I have class:
#Service
public class A {
#Value("${a.b.c}")
private String abc;
public void foo() {
sout(abc);
}
}
I Have test class:
#SpringBootTest
#SpringBootConfiguration
#RunWith(SpringRunner.class)
#TestPropertySource(locations = "classpath:application.yml")
public class TestA {
#Value("${a.b.c}")
private String abc;
#InjectMocks
private A a;
#Test
public void testFoo() {
this.a.foo();
}
}
When I debugging the test method testFoo(),
I see that variable abc is read from the application.yml file.
But,
inside the foo() method,
I see that the variable abc is null.
How can I set variable abc such that it is available in method foo() when I trying to test this method?
Step one is to answer this question: Am I unit testing the code in my class or am I integration testing the combination of Spring and some collection of code that includes my class?
If you are unit testing your code,
then it is not necessary to have Spring do its thing.
Instead,
you only need to instantiate your class,
set the values that Spring would have set for you,
execute the method you are testing,
then verify that your method executed correctly.
Here is your example unit test rewritten as I suggested:
public class TestA
{
private static final String VALUE_ABC = "VALUE_ABC";
private A classToTest;
#Test
public void testFoo()
{
classToTest.foo();
}
#Before
public void preTestSetup()
{
classToTest = new A();
ReflectionTestUtils.setField(
classToTest,
"abc",
VALUE_ABC)
}
}
Some Notes:
ReflectionTestUtils is part of Spring-test.
You don't need to use #InjectMocks because you have no mocks to inject.
I don't know what sout is, so I excluded it from the test. You should verify that the sout method was called with the correct value (in this case VALUE_ABC).
If you are just unit testing your code, you don't need Spring, which means that you don't need to use the #RunWith annotation.
You can try to overide the properties like that:
#TestPropertySource(locations = "location.properties",
properties = "a.b.c=123")
Example taken from here
I'm using Mockito in some tests.
I have the following classes:
class BaseService {
public void save() {...}
}
public Childservice extends BaseService {
public void save(){
//some code
super.save();
}
}
I want to mock only the second call (super.save) of ChildService. The first call must call the real method. Is there a way to do that?
If you really don't have a choice for refactoring you can mock/stub everything in the super method call e.g.
class BaseService {
public void validate(){
fail(" I must not be called");
}
public void save(){
//Save method of super will still be called.
validate();
}
}
class ChildService extends BaseService{
public void load(){}
public void save(){
super.save();
load();
}
}
#Test
public void testSave() {
ChildService classToTest = Mockito.spy(new ChildService());
// Prevent/stub logic in super.save()
Mockito.doNothing().when((BaseService)classToTest).validate();
// When
classToTest.save();
// Then
verify(classToTest).load();
}
No, Mockito does not support this.
This might not be the answer you're looking for, but what you're seeing is a symptom of not applying the design principle:
Favor composition over inheritance
If you extract a strategy instead of extending a super class the problem is gone.
If however you are not allowed to change the code, but you must test it anyway, and in this awkward way, there is still hope. With some AOP tools (for example AspectJ) you can weave code into the super class method and avoid its execution entirely (yuck). This doesn't work if you're using proxies, you have to use bytecode modification (either load time weaving or compile time weaving). There are be mocking frameworks that support this type of trick as well, like PowerMock and PowerMockito.
I suggest you go for the refactoring, but if that is not an option you're in for some serious hacking fun.
Consider refactoring the code from ChildService.save() method to different method and test that new method instead of testing ChildService.save(), this way you will avoid unnecessary call to super method.
Example:
class BaseService {
public void save() {...}
}
public Childservice extends BaseService {
public void save(){
newMethod();
super.save();
}
public void newMethod(){
//some codes
}
}
I found a way to suppress the superclass method using PowerMockito. 3 simple steps need for this
Use PowerMockito.suppress method and MemberMatcher.methodsDeclaredIn method to supress parent class method
Second add Parent class in #PrepareForTest
Run your test class with PowerMock ie add #RunWith(PowerMockRunner.class) above your test class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({BaseService.class})
public class TestChildService(){
#Spy
private ChildService testChildServiceObj = Mockito.spy(new ChildService());
#Test
public void testSave(){
PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(BaseService.class));
//your further test code
testChildServiceObj.save();
}
}
Note: This will work only when the superclass method does not return anything.
Maybe the easiest option if inheritance makes sense is to create a new method (package private??) to call the super (lets call it superFindall), spy the real instance and then mock the superFindAll() method in the way you wanted to mock the parent class one. It's not the perfect solution in terms of coverage and visibility but it should do the job and it's easy to apply.
public Childservice extends BaseService {
public void save(){
//some code
superSave();
}
void superSave(){
super.save();
}
}
create a package protected (assumes test class in same package) method in the sub class that calls the super class method and then call that method in your overridden sub class method. you can then set expectations on this method in your test through the use of the spy pattern. not pretty but certainly better than having to deal with all the expectation setting for the super method in your test
Even if i totally agree with iwein response (
favor composition over inheritance
), i admit there are some times inheritance seems just natural, and i don't feel breaking or refactor it just for the sake of a unit test.
So, my suggestion :
/**
* BaseService is now an asbtract class encapsulating
* some common logic callable by child implementations
*/
abstract class BaseService {
protected void commonSave() {
// Put your common work here
}
abstract void save();
}
public ChildService extends BaseService {
public void save() {
// Put your child specific work here
// ...
this.commonSave();
}
}
And then, in the unit test :
ChildService childSrv = Mockito.mock(ChildService.class, Mockito.CALLS_REAL_METHODS);
Mockito.doAnswer(new Answer<Void>() {
#Override
public Boolean answer(InvocationOnMock invocation)
throws Throwable {
// Put your mocked behavior of BaseService.commonSave() here
return null;
}
}).when(childSrv).commonSave();
childSrv.save();
Mockito.verify(childSrv, Mockito.times(1)).commonSave();
// Put any other assertions to check child specific work is done
You can do this with PowerMockito and replace behavior only of the parent class method with continuing testing the child's class method. Even when the method is returning some value, lets say a string, you can do something like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ BaseService.class })
public class TestChildService() {
private BasicService basicServiceObj;
private ChildService testee;
#Before
public void init() throws Exception {
testee = new ChildService();
basicServiceObj = PowerMockito.spy(new BaseService());
PowerMockito.doReturn("Result").when(basicServiceObj, "save", ... optionalArgs);
}
#Test
public void testSave(){
testee.save();
}
}
If you are returning nothing (void) then instead of doReturn you can use doNothing. Add some optionalArgs if the method have some arguments, if not, then skip that part.
The reason is your base class is not public-ed, then Mockito cannot intercept it due to visibility, if you change base class as public, or #Override in sub class (as public), then Mockito can mock it correctly.
public class BaseService{
public boolean foo(){
return true;
}
}
public ChildService extends BaseService{
}
#Test
#Mock ChildService childService;
public void testSave() {
Mockito.when(childService.foo()).thenReturn(false);
// When
assertFalse(childService.foo());
}
There is simple approach that works for most of cases. You can spy your object and stub the method you want to mock.
Here is an example:
MyClass myObjectSpy = Mockito.spy(myObject);
org.mockito.Mockito.doReturn("yourReturnValue").when(mySpyObject).methodToMock(any()..);
So, when you test your object, you can use myObjectSpy and when methodToMock is called, it will overwrite the normal behavior by a mock method.
This code for a method with return. In case you have a void method you can use doNothing instead.
I want to test a class, which extends a superclass. I use JUnit and Mockito. In one method this class calls a supermethod of the superclass:
#Override
public void init(String input){
super.init();
...
}
Now in my test-class I already have following setup:
#InjectMocks
private MyClass classUnderTest = new MyClass();
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
Now how do I mock the super.method call? I don't think Spying will help in this case.
You should not be mocking this call. You should not have inheritance here at all. If class A needs to call method b() which is tested elsewhere and you don't care about what it does, it means that method b() should be in class B which is a dependency of class A - and then you can do dependency injection and mock B.
If this is some legacy code that you cannot change, one of interesting strategies of refactoring it is making a new method in class A and overriding it in your test (by either extending A or spying on this method):
class A extends B {
private void b() {
// something here
super_b();
}
protected void super_b() {
super.b();
}
}
I have a class Dummy. I inject 3 variables. However, one of them is not injectable because it is an interface. So I inject an object, one of whose methods return the needed type.
Class Dummy
{
private final Class1 class1;
private final Class2 class2
private final Interface1 interface1;
#Inject
Dummy(Class1 class1, Class2 class2, HelperClass helperclass)
{
this.class1 = class1;
this.class2 = class2;
this.interface1 = helperclass.somefunction();
}
}
The HelperClass's somefunction returns an instance of Interface1.
This is my test:
#RunWith(MockitoJUnitRunner.class)
Class DummyTest
{
#Mock
private Class1 class1;
#Mock
private Class2 class2;
#Mock
private HelperClass helperclass;
#InjectMocks
private Dummy dummy;
#Before
public void start()
{
Interface1 mockInterface = mock(Interface1.class);
when(helperclass.somefunction()).thenReturn(mockInterface);
}
#Test
public void test()
{
// etc...
}
}
However, interface1 is null when I run the test. What am I doing wrong?
#InjectMocks happens before the #Before annotation.
For this reason (and other reasons), I recommend not using #InjectMocks at all; just build your SUT class in the #Before method with a real constructor.
This ordering is obvious when you add a few print statements to your test class. I removed all the Class1 and Class2 stuff as it's not relevant. See this code run:
#RunWith(MockitoJUnitRunner.class)
public class DummyTest {
#Mock
private HelperClass helperclass;
#InjectMocks
private Dummy dummy;
#Before
public void start()
{
System.out.println("In #Before!");
Interface1 mockInterface = mock(Interface1.class);
when(helperclass.somefunction()).thenReturn(mockInterface);
}
#Test
public void test()
{
System.out.println("In #Test!");
}
public static class Dummy {
public final Interface1 interface1;
public final HelperClass helperclass;
#Inject
Dummy(HelperClass helperclass)
{
System.out.println("In dummy constructor!");
this.interface1 = helperclass.somefunction();
this.helperclass = helperclass;
}
}
private static class HelperClass {
Interface1 somefunction() {
return new Interface1() {};
}
}
private static interface Interface1 {
}
}
Output:
In dummy constructor!
In #Before!
In #Test!
If you insist on doing it with #Mock and #InjectMocks, you could try using the answer argument instead:
#Mock(answer=Answers.RETURNS_MOCKS)
will make helperclass.somemethod() return a mock instead of null.
Honestly, it's not surprising that it works this way. The authors of Mockito really don't like Partial Mocks / Stubs, and explicitly say so in their documentation:
As usual you are going to read the partial mock warning: Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects. How does partial mock fit into this paradigm? Well, it just doesn't... Partial mock usually means that the complexity has been moved to a different method on the same object. In most cases, this is not the way you want to design your application.
However, there are rare cases when partial mocks come handy: dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.) However, I wouldn't use partial mocks for new, test-driven & well-designed code.
Having helperclass return something other than null is a partial mock, and therefore they won't like it.
I want to mock the DAO interface used in the builder pattern as shown below. However when I run the test below it passes indicating that my mock object is never called. What am I doing wrong?
public class DBContent {
...
public static class Builder {
DAO dao = new DAO();
...
public Builder callInsert() {
...
long latest = dao.insert();
...
}
}
...
}
#RunWith(MockitoJUnitRunner.class)
public class DBContentTest {
#Mock
DAO dao;
#Test
public void test() {
when(dao.insert()).thenReturn(1111L);
DBContent db = DBContent.db()
.callInsert()
.callInsert()
.callInsert()
.build();
verifyZeroInteractions(dao);
}
}
Use PowerMockito instead. There you can define that whenever you have a call to a constructor of DAO, return my mocked object instead of returning actual DAO object.
Please refer this to learn how to use PowerMockito.