Mockito: Spying calls within the constructor (Java) [duplicate] - java

This question already has answers here:
Test class with a new() call in it with Mockito
(7 answers)
Closed 5 years ago.
This is not a duplicate of Test class with a new() call in it with Mockito. I'm trying to write a test to verify that certain methods are being called within the constructor of my spy object (mockToyFacade).
The class under test is ToyFactoryFacade. The idea is clients interact with the ToyFactoryFacade (which wraps a ToyFactory) to generate ToyFacades, which itself is a wrapper around the Toy object.
What I am trying to verify with Mockito?
I want to verify that addToyName(toyName) and addCreationTime(creationTimestamp) are being called on the ToyFacade. Both of these methods are called in the constructor of the ToyFacade.
What's the issue?
When I try to spy the ToyFacade, and verify that both aforementioned methods are called, I receive an error, which says "Actually, there were zero interactions with this mock." When I call the methods separately (i.e., not via the constructor), the verification check out correctly. I'm not sure what I'm doing incorrectly.
Test Code
public class ToyFactoryFacadeTest {
private Toy mockToy;
private ToyFacade mockToyFacade;
// System under test.
private ToyFactoryFacade toyFactoryFacade;
private ToyFactory mockToyFactory;
#Before
public void setup() {
mockToy = mock(Toy.class);
mockToyFacade = spy(new ToyFacade(mockToy, "Phone", System.currentTimeMillis()));
mockToyFactory = mock(ToyFactory.class);
toyFactoryFacade = new ToyFactoryFacade(mockToyFactory) {
#Override
public Toy getToyFacade(String toyName, long creationTimestamp){
return mockToyFacade;
}
};
}
#Test
public void testToyFactoryFacade() {
toyFactoryFacade.initializeAndGetToy("Phone", System.currentTimeMillis());
verify(mockToyFacade).addToyName("Phone");
verify(mockToyFacade).addCreationTime(anyLong());
}
}
Source Code
public class ToyFactoryFacade {
private final ToyFactory toyFactory;
public ToyFactoryFacade(ToyFactory toyFactory) {
this.toyFactory = toyFactory;
}
public ToyFacade initializeAndGetToy(String toyName, long creationTimestamp)
{
getToyFacade(toyName, creationTimestamp);
}
// For testing.
protected ToyFacade getToyFacade(String toyName, long creationTimestamp
{
return new ToyFacade(toyFactory.newToy(), toyName, creationTimestamp);
}
}
public class ToyFactory {
public Toy newToy() {
return new Toy();
}
}
public class ToyFacade {
private final Toy toy;
public ToyFacade(Toy toy, String toyName, long creationTimeStamp) {
this.toy = toy;
addToyName(toyName);
addCreationTime(creationTimestamp);
}
public void addToyName(String name) {
toy.addToyName(toyName);
}
public void addCreationTime(long timestamp) {
toy.addCreationTime(timestamp);
}
}
public class Toy {
public String toyName;
public String creationTimestamp;
public void addToyName(String name) {
toyName = name;
}
public void addCreationTime(long timestamp) {
creationTimestamp = timestamp;
}
}

Your test isn't doing what you expect because the method calls that you're trying to verify have already taken place before you create your spy. What you really want to do is to test the effect of those two method calls, rather than the calls themselves. This would look something like
verify(mockToy).addToyName("Phone");
verify(mockToy).addCreationTime(timestamp);
where timestamp is whatever you pass in in the setUp method.

Related

JMockit verify if private method is called

I am testig a public method and I want to verify if a private method, that have mocked params, is called.
All the answers I have found are using invoke method, but this was removed since JMockit v1.36
public class ClassToTest{
public void methodToTest(){
DependencyClass abc = new DependencyClass();
if(privateMethod1()){
privateMethod2(abc);
}
}
private boolean privateMethod1(){ return true; }
private void privateMethod2(DependencyClass abc){ abc.doStuff(); }
}
public class testClassToTest{
#Mocked
DependencyClass abc;
#Tested
ClassToTest testedClass;
#BeforeEach
public void setUp() {
testedClass = new ClassToTest();
}
#Test
public void testMethod(){
new MockUp<ClassToTest>() {
#Mock
private boolean privateMethod1() {
return true;
}
};
testedClass.methodToTest();
new FullVerificationsInOrder() {{
abc = new DependencyClass();
//Check here if privateMethod2(abc) gets called once
}};
}
You can use Powermock to mock and verify private methods.
Please check https://github.com/powermock/powermock/wiki/MockPrivate
You have two ways:
To level up your method's scope from private to package-private and after it, your method will become visible in the test.
Refactoring your code and encapsulate the private method to Predicate and after it, you can test your primary method and Predicate separately.
You can't test the private method by Junit.

Mock or override static method to test a class

I'm doing some unit test but I'm having problems trying to test a class. I have a class with a static builder method which returns the class instance:
public class MessageCaller {
public static MessageCaller builder() {
return new MessageCaller();
}
//Other methods
public String publish() {
//publishing to some Messages
return "something";
}
public MessageCaller withAttribute(String key, String value) {
//Some code
return this;
}
}
public class MessageCallerExtended extends MessageCaller {
private Map<String, String> attributes;
#Override
public MessageCaller withAttribute(String key, String value) {
if (this.attributes == null) {
this.attributes = new HashMap();
}
this.attributes.put(key, value);
return this;
}
//It's not working because it's calling the base class builder and is not possible to be Overriten
//because it's a static method.
public static MessageCallerExtended builder() {
return new MessageCallerExtended();
}
#Override
public String publish() {
return "test";
}
}
This is the method which I would like to test, the problem is that is calling the real publish method taking some time to finalize.
public void sendMessages(#Nonnull String group, #Nonnull String state) {
this.message.builder()
.toTopic(xxxx)
.withAttribute(xxx, xxx)
.withAttribute(xxx, xxx)
.withAttribute(xxx,xxx)
.publish();
}
I'm sending the message object in the constructor of the class.
I've created a Wrapper class to use in the unit test but the problem is that the builder method is static and for that reason is not possible to #Override, if I don't use the #Override tag I'll invoke the real builder method and then the real publish method and it is taking too much time to be processed, causing some problems, because is invoked for several unit test.
With Mockito I having similar issues with the static builder method, in fact it's not possible to mock static methods with Mockito. I'm not allowed to use another library like PowerMock for instance.
Any ideas?

Verifying no argument and private methods using Mockito [duplicate]

This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 3 years ago.
I am new to JUnit & Mockito, the below class is defined with a method execute which needs to be tested, I wonder is it possible to mock this type of class ? Please shed some light and share your thoughts.
public class MyRule implements SuperRule{
private OrderList orderList;
private ScheduleList scheduleList;
public MyRule (OrderList orderList, ScheduleList scheduleList) {
this.orderList = orderList;
this.scheduleList = scheduleList;
}
#Override
public void execute() {
createWeeklyClassificationRule(orderList);
handle(scheduleList);
}
private void createWeeklyClassificationRule(OrderList orderList) {
//......
}
private void handle(ScheduleList scheduleList) {
//......
}
}
You could mock scheduleList and orderList instead and use verify to make sure the correct methods are being called from them.
public class MyRuleTest
{
private MyRule myRule;
private ScheduleList scheduleListMock;
private OrderList orderListMock;
#Before
public void setUp() throws Exception
{
scheduleListMock = mock(ScheduleList.class);
orderListMock = mock(OrderList.class);
myRule = new MyRule(orderListMock, scheduleListMock);
}
#Test
public void testExecute()
{
myRule.execute();
verify(scheduleListMock).foo();
verify(orderListMock).bar();
}
...
You would just replace foo and bar with whatever methods you are expecting to be called.
If you are testing MyRule, you shouldn't be mocking it. A good rule of thumb is to not mock the class that is under test.

How do I test Function's code when it's passed as method parameter?

Is it possible to test code that is written in lambda function that is passed inside the method process?
#AllArgsConstructor
public class JsonController {
private final JsonElementProcessingService jsonElementProcessingService;
private final JsonObjectProcessingService jsonObjectProcessingService;
private final JsonArrayProcessingService jsonArrayProcessingService;
public void process(String rawJson) {
jsonElementProcessingService.process(json -> {
JsonElement element = new JsonParser().parse(json);
if (element.isJsonArray()) {
return jsonArrayProcessingService.process(element.getAsJsonArray());
} else {
return jsonObjectProcessingService.process(element.getAsJsonObject());
}
}, rawJson);
}
}
Since the lambda is lazy the function is not invoked (Function::apply) when I call JsonController::process so is there any way to check that jsonArrayProcessingService::process is called?
#RunWith(JMockit.class)
public class JsonControllerTest {
#Injectable
private JsonElementProcessingService jsonElementProcessingService;
#Injectable
private JsonObjectProcessingService jsonObjectProcessingService;
#Injectable
private JsonArrayProcessingService jsonArrayProcessingService;
#Tested
private JsonController jsonController;
#Test
public void test() {
jsonController.process("[{\"key\":1}]");
// how check here that jsonArrayProcessingService was invoked?
}
}
Just make it testable (and readable) by converting it to a method:
public void process(String rawJson) {
jsonElementProcessingService.process(this::parse, rawJson);
}
Object parse(String json) {
JsonElement element = new JsonParser().parse(json);
if (element.isJsonArray()) {
return jsonArrayProcessingService.process(element.getAsJsonArray());
} else {
return jsonObjectProcessingService.process(element.getAsJsonObject());
}
}
The relevant guiding principles I personally follow are:
anytime my lambdas require curly brackets, convert them to a method
organise code so that it can be unit tested
You may need to change the return type of the parse method to match whatever your processing services (which you didn’t show) return.
Given its relatively-basic redirection logic, don't you just want to confirm which of the #Injectables got called:
#Test
public void test() {
jsonController.process("[{\"key\":1}]");
new Verifications() {{
jsonArrayProcessingService.process(withInstanceOf(JsonArray.class));
}};
}

Fields don't match but the test was still passed. [Mockito Test]

I have the following test set up. I don't understand how the test is passing successfully since the user is set to "Dummy."
#RunWith(MockitoJUnitRunner.class)
public class TodoServiceAbstractImplTest
{
#InjectMocks
TodoServiceAbstractImpl todoServiceAbstractImpl = new TodoServiceAbstractImpl();
#Mock
SomeRandomClass someRandomClass;
#Mock
TodoServiceAbstract todoServiceAbstract;
#Test
public void testRetrieveTodo_usingAMock(){
todoServiceAbstractImpl.setUser("Dummy"); //Set the user to be "Dummy" already
assertEquals(null,todoServiceAbstractImpl.getUser()); //Why is the user is still null?
}
}
Here are the relevant classes. I created them to test Mockito as I am still learning testing in Spring Boot.
Definition of the SomeRandomClass:
public class SomeRandomClass{
private String field;
public SomeRandomClass(){
}
public SomeRandomClass(String field){
setRandom(field);
}
public void setRandom(String field){
this.field = field;
}
public String getRandom(){
return field;
}
}
Definition of the Abstract class:
public abstract class TodoServiceAbstract {
#Autowired
private SomeRandomClass RandomUser;
public TodoServiceAbstract(){
//RandomUser = new SomeRandomClass();
}
public void setUser(String user){
this.RandomUser.setRandom(user);
}
public String getUser(){
return RandomUser.getRandom();
}
public abstract List<String> retrieveTodos(String user);
}
Definition of the Abstract Implementation
public class TodoServiceAbstractImpl extends TodoServiceAbstract{
public List<String> retrieveTodos(String user){
if(user == getUser()){
return Arrays.asList("item 1", "item 2",
"item 3");
}
return Arrays.asList("Random item");
}
}
Tom answered in the comments:
Why do you expect something else than null? SomeRandomClass is mocked so it obviously doesn't actually set anything when calling setUser. And why should it? That's the point of a mock.
Remember that mocked implementations are not real, and in particular unstubbed calls will return dummy values such as null, 0, or an empty string.
In addition to what Tom already said in the comments, this test is testing your mocks, rather than your actual implementation. Since you mocked SomeRandomClass, your tests should verify if that method is being called. In this case you should test if SomeRandomClass.setRandom() is called when you call setUser() and likewise, you should test if SomeRandomClass.getRandom() is called when you call getUser().
For example:
#Test
public void getUser_shouldUseGetRandom() {
when(someRandomClass.getRandom()).thenReturn("data");
assertEquals("data", todoServiceAbstractImpl.getUser());
}
To test setUser() you can do something like:
#Test
public void setUser_shouldUseSetRandom() {
todoServiceAbstractImpl.setUser("data");
verify(someRandomClass).setRandom("data");
}
By mocking/stubbing you can write proper unit tests for TodoServiceAbstractImpl without having to take the behaviour of SomeRandomClass.

Categories

Resources