I have class class1, which has 2 member variables:
classA
{
private Boolean isEnable;
private Config config;
public classA(final Config config)
{
this.config = config;
isEnable = config.getEnablingStatus();
}
public classB fun()
{
// Do something!
// Return an object of classB!
}
}
I want to test the method fun, so I will have to write a test-class and a test method for that. But, how do I mock the method call config.getEnablingStatus(), while creating an object of type classA in the test class?
I am thinking of doing something like this [see the below piece of code].Is it correct? But what is the right way to do it?
TestClassForClassA:
TestClassForClassA
{
private Boolean isEnable;
#Mock
private Config config;
#InjectMocks
classA objA = new classA(config);
#Before
public void init()
{
initMocks(this);
}
public void test1Fun()
{
// Does doing this, put the value of isEnable as true in the objA for this test?
isEnable = true;
// Here write the code to test the method fun().
}
public void test2Fun()
{
// Does doing this, put the value of isEnable as false in the objA for this test?
isEnable = false;
// Here write the code to test the method fun().
}
}
Do not use #InjectMocks
Try something like this
public class TestClassForClassA {
#Mock
private Config config;
private ClassA objA;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test1Fun() {
Mockito.when(config.getEnablingStatus()).thenReturn(true);
objA = new ClassA(config);
ClassB objB = objA.fun();
assertTrue(objB.isEnabled());
}
#Test
public void test2Fun() {
Mockito.when(config.getEnablingStatus()).thenReturn(false);
objA = new ClassA(config);
ClassB objB = objA.fun();
assertFalse(objB.isEnabled());
}
}
Related
I have the following scenario.
public class A {
//constructors
#Value(${useMethodA:false})
private boolean isUseMethodAEnabled;
public void func() {
if(isUseMethodAEnabled()) {
a();
} else {
b();
}
}
}
//methods a() and b()
public class B {
#Autowired
private A a;
public void funcPrincipal() {
A.a();
System.out.println("Method A.a() was called");
}
}
#RunWith(MockitoJUnitRunner.class)
public class BTest {
#InjectMocks
private B b;
#InjectMocks
#Spy
private A a = new A();
#Test
public void test() {
ReflectionTestUtils.setField(a, "isUseMethodAEnabled", true);
b.funcPrincipal();
// if A is annotated with #Spy -> the "isUseMethodAEnabled" is always false
}
}
See the above comment, please.
Is there any solution to change the "isUseMethodAEnabled" value from false to true using reflection?
If I switch to #Mock instead of #Spy everything works as expected. But for my test cases, I must use #Spy + #InjectMocks.
I have mocked another class method called Which is called at production like new B().somemethod (arg) has return type void and newD().anymenthod() it has return type inputstream
In the test method, I am doing mocking Like donothing().when(b). somemethod ();
And
When(d.anymehod()).thenreturn(inputstream);(here inputstrem i am providing)
Here I already did #Mock B b;
#Mock D d;
Here my test case run successfully but mocked method was also called at that time.
Here I didn't want to alter the production code only test cases implementation can be altered.
class TestSystem {
#InjectMock
System sys;
#Mock
B b;
#Mock
D d;
#BeforeEach
void setup() {
MockitoAnnotation.openMocks(this);
}
#Test
testModule() {
InputStrem input = null;
when(d.anymethod()).thenReturn(inputStrem);
doNothing().when(b).somemethod();
sys.module();
}
Class System{
public void module() {
//some code .....
new B().somemethod();
inputStrem = new D().anymethod(value);
}
Class B {
public void somemethod(){
//some code .....
}
}
Class D {
public InputStrem anymethod() {
//some code ......
}
}
Try to initialise Mock like this:
#InjectMocks
private System sys;
#Mock
B b;
#Mock
D d;
private AutoCloseable closeable;
#BeforeEach
void init() {
closeable = MockitoAnnotations.openMocks(this);
}
#AfterEach
void closeService() throws Exception {
closeable.close();
}
#Test
testModule(){...}
using Spring 2.0.3.RELEASE, JUnit Jupiter 5.7.0, Mockito 3.3.3
try to test method method01 of class Class01:
public class Class01 {
private RestConnector con;
public Class01(){
con = RestConnector.getInstance();
}
public Response method01(String x) {
Class01 example = new Class01();
String x = example.isAuthenticated();
// more stuff after this
}
public String isAuthenticated() throws IOException {
// I do stuff
return "a string";
}
}
In the test class have tried
public class Class01Test{
#Mock private Class01 class01Mock;
#Spy #InjectMocks private Class01 class01;
#Test
public void test() throws Throwable {
doReturn("I returned").when(class01). ??? stuck here .. always goes into the isAuthenticated method
Response result = class01.method01("a string");
}
}
Currently the test is always running the real method isAuthenticated.
How to setup a mock for the field example in method method01 so that the execute skips going into method isAuthenticated?
try to test method method01 of class Class01
Then you don't need mocks.
#Test
public void test() throws Throwable {
Class01 c = new Class01();
Response expected = ... ;
assertEquals(c.method01("input"), expected);
}
If you want to inject behaviour into example variable, you need to move it to a field
public class Class01 {
private RestConnector con;
private Class01 inner;
public Class01(){
con = RestConnector.getInstance();
}
Class01(Class01 c) {
this();
this.inner = c;
}
public Response method01(String x) {
String x = inner.isAuthenticated();
// more stuff after this
}
Along with a Mock
#RunWith(MockitoJunitRunner.class)
public class Class01Test{
#Mock Class01 class01Mock;
#Test
public void test() throws Throwable {
Response expected = ... ;
when(class01Mock.isAuthenticated()).thenReture(expected); ... // TODO: Setup
Class01 c = new Class01(class01Mock); // pass in the mock
assertEquals(c.method01("input"), expected);
}
However, unclear why you need a nested object of the same class when you appear to only need this.isAuthenticated()
Ideally, you'd also mock the RestConnector
So my class is:
public final class MyClass {
private static MyObject myObject;
public static void setMyObject(MyObject myObject) {
MyClass.myObject = myObject;
}
private MyClass(MyObject myObject){
setMyObject(myObject);
}
public static Optional<Object2> getObject2(params) {
Optional<Object2> object2 = myObject.execute(params);
return object2;
}
I'm trying to test with Junit
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock
private MyObject myObject;
private MyClass myClass;
#Before
public void initialize() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test1() {
Mockito.doReturn(Optional.empty()).when(myObject).executeQueryWithArgument(any);
myclass = new Myclass(myObject);
}
}
myclass = new Myclass(myObject);
This line fails and says make MyClass constructor package private. Is there any way to do this without doing that?
Add mocked myObject to the MyClass using the set method and write the test, like this:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock
private MyObject myObject;
private MyClass myClass;
#Before
public void setUp() {
MyClass.setMyObject(myObject);
}
#Test
public void shouldDoSomething() {
// Arrange
Mockito.doReturn(Optional.empty()).when(myObject).executeQueryWithArgument(any);
// Act
Optional<Object2> actual = myClass.getObject2(.....);
// Assert
.....
}
}
If I have the following;
public class ClassA {
public void methodA(){
System.out.println("In ClassA, methodA");
}
}
public class ClassB {
public void methodB(){
}
}
and a junit test of;
#Test
public void testMocked(#Mocked final ClassB mockedB) {
System.out.println("Mocked inline");
new MockUp<ClassA>() {
#Mock
public void methodA() {
System.out.println("Inline mockup, mockedB:" + mockedB);
}
};
ClassA a = new ClassA();
a.methodA();
}
Then when I run the test I get;
Mocked inline
Inline mockup, mockedB:jmockitpractice.ClassB#329b0985
Which is as expected, the classB is Mocked, and an instance is available.
But, if I change this to create a helper class for mocking,
public class MockHelper {
#Mocked ClassB classB;
public void setupMocks(){
new MockUp<ClassA>() {
#Mock
public void methodA(){
System.out.println("In setupMocks, classB:"+classB);
}
};
}
}
and the junit becomes;
#Test
public void testMockedInClass() {
System.out.println("Mocked in helper class");
MockHelper mh = new MockHelper();
mh.setupMocks();
ClassA a = new ClassA();
a.methodA();
}
the result I get is;
Mocked in helper class
In setupMocks, classB:null
classB is not initialized by the #Mocked inside MockHelper
I would like to have all the mocking in a helper class, rather than having to declare all the mocking in the test class.
Any ideas why this doesn't work?
Thanks.
Thanks Dom Farr, the answer was inheritance.
public class MockHelper {
#Mocked
ClassB classB;
public void setupMocks() {
new MockUp<ClassA>() {
#Mock
public void methodA() {
System.out.println("In setupMocks, classB:" + classB);
}
};
}
}
and
public class mockTest extends MockHelper {
#Test
public void testMockedInClass() {
System.out.println("Mocked in helper class");
setupMocks();
ClassA a = new ClassA();
a.methodA();
}
}
As the test class extends the helper, it now works;
Mocked in helper class
In setupMocks, classB:jmockitpractice.ClassB#5d54e317