Mockito : how to verify method was called on an object created within a method?
Dependency Injection
If you inject the Bar instance, or a factory that is used for creating the Bar instance (or one of the other 483 ways of doing this), you'd have the access necessary to do perform the test.
Factory Example:
Given a Foo class written like this:
public class Foo {
private BarFactory barFactory;
public Foo(BarFactory factory) {
this.barFactory = factory;
}
public void foo() {
Bar bar = this.barFactory.createBar();
bar.someMethod();
}
}
in your test method you can inject a BarFactory like this:
@Test
public void testDoFoo() {
Bar bar = mock(Bar.class);
BarFactory myFactory = new BarFactory() {
public Bar createBar() { return bar;}
};
Foo foo = new Foo(myFactory);
foo.foo();
verify(bar, times(1)).someMethod();
}
Bonus: This is an example of how TDD(Test Driven Development) can drive the design of your code.
Mockito How to test that an instance created inside a method is calling methods
You have three alternatives:
- Using the injection
- Using PowerMockito
- Refactor the code in a test friendly manner
Using the injection
If the object Obj is injected in your class under test, instead of has been initialized in the method, you will be able to inject a mock and then use the expression
verify(obj).callsMethod()
that you already knew and that is right.
Using PowerMockito
With powermockito you can write something like this
@RunWith(PowerMockRunner.class)
@PrepareForTest({Obj.class})
class MyJunit{
....
@Test
public void test() throws Exception{
Obj myMock = Mockito.mock(Obj.class);
PowerMockito.whenNew(Obj.class).withAnyArguments().thenReturn(myMock);
// here your test
}
At this point you can use the expression you already knew and that is right.
Refactor
You can use a protected
method in order to build th Obj
and mock this method in your junit in order to return a mock version of the Obj and then use the expression you already knew and that is right.
Mockito: How to verify a method was called only once with exact parameters ignoring calls to other methods?
Mockito.verify(foo, Mockito.times(1)).add("1");
Mockito.verify(foo, Mockito.times(1)).add(Mockito.anyString());
The first verify
checks the expected parametrized call and the second verify
checks that there was only one call to add
at all.
Mockito, how to verify if the method of the tested class was called?
You won't be able to use Mockito to verify that method is called, but you can verify the output from the getAll()
method given that you've mocked out the response to dishRepository.findAll()
. So, in effect, just add some assertions after your verify calls that match your expected data with the actual data, I assume that this::toDishResponseDTO
just return a Dish
.
@Test
void shouldCallFindAllReturnDto_whenV() {
Mockito.when(dishRepository.findAll()).thenReturn(TestData.ENTITY_DISH);
List<Dish> dishes = dishService.getAll();
Mockito.verify(dishRepository, times(1)).findAll();
assertThat(dishes, is(notNullValue());
assertThat(dishes.get(0).getSomeField, is(equalTo("someValue")));
}
How to use Mockito to verify a method is called in another method?
You can't use Mockito if you create a new ClassB instance in your method.
You should refactor publish() to take ClassB as a parameter, and then you can send your Mockito mock instead of a real ClassB, and verify on it.
Like so:
public class A {
public void publish(ClassB classb){
classb.sendRequest(this)
}
}
And in your test:
ClassB mockClassB = mock(ClassB.class);
A a = new A();
a.publish(mockClassB);
verify(mockClassB, times(1)).sendRequest(any());
How to verify a method inside a method is called in mockito
You mocked A
and replaced it with MockA
. Mocks have no implementation. MockA.doSomething()
does nothing and does not and cannot call MockA.callMe()
.
That A.doSomething()
calls A.callMe()
should be considered an implementation detail of of doSomething()
; making a test rely on that would tightly couple the test to the specific implementation and would be brittle.
You can't use a mock to verify the implementation of the thing being mocked. If you want to verify the implementation of A.doSomething()
, you instead should use an actual object and verify observable properties on that object.
But if you still really want to do this, then you would need to modify A
to not call methods on itself and to instead call methods on a provided object (i.e., "dependency injection"). For example:
class A {
final late A a;
A({A? a}) {
this.a = a ?? this;
}
void doSomething() {
a.callMe();
}
void callMe() {}
}
test("Test method is called", () {
var mockA = MockA();
var actualA = A(a: mockA);
actualA.doSomething();
verify(mockA.callMe()).called(1);
});
It's a bit unusual for a class to depend on a mock of itself, however, and it would not scale if you then want to verify calls made by callMe()
.
Another approach that would scale better (but with significantly more work) would be to create your own fake class that tracks method calls:
class TrackedA implements A {
int doSomethingCallCount = 0;
int callMeCallCount = 0;
@override
void doSomething() {
doSomethingCallCount += 1;
super.doSomething();
}
@override
void callMe() {
callMeCallCount += 1;
super.callMe();
}
}
But again, that's very brittle, and I would not recommend it.
Mockito - Verify if an object in a set called a method
You could simply invoke the verify on each mocked element of the Set :
for (MyType myType : myTypes) {
verify(myType, times(3))
.getName();
}
But this will not work with the actual code because myTypes
is defined as a Mock
:
@Mock
private Set<MyType> myTypes = (Set<MyType>) mock(Set.class);
And you didn't record any behavior for it.
So you could never iterate on elements added as elements will never be added in the Set
as you do that :
MyType mT = Mockito.mock(MyType.class);
mT.setName("Name" + i);
myTypes.add(mT);
In fact myTypes
has not to be a mock.
Declare it as a plain object :
private Set<MyType> myTypes = new HashSet<>();
You don't need to spy the object under test either.
You want to verify invocation of mocks
, not invocations of the object under test.
So you can also replace :
TestObject testObject = Mockito.spy(new TestObject());
by :
TestObject testObject = new TestObject();
Note that spying is not a good practice but a workaround. So avoid that as you can and above all as you don't need it !
And it should be fine.
Related Topics
Eclipse Windowbuilder, Overlapping JPAnels
Spring Cache @Cacheable - Not Working While Calling from Another Method of the Same Bean
Connecting an Input Stream to an Outputstream
Springboot 2.6.0/Spring Fox 3 - Failed to Start Bean 'Documentationpluginsbootstrapper'
How to Manage Rest API Versioning with Spring
Securing a Password in a Properties File
What Is the Fastest Way to Compare Two Sets in Java
Graphics Rendering in Title Bar
How to Call a Method with a Separate Thread in Java
Shared Memory Between Two Jvms
The Server Time Zone Value 'Aest' Is Unrecognized or Represents More Than One Time Zone
How to Change the Shape of a Jtabbedpane Tab
Spring: Why Do We Autowire the Interface and Not the Implemented Class