Hello I am struggling with simple problem.
General idea:
class Foo(){
public boolean method1();
public String method2();
public String method3();
public String shortcut(){
return (method1() == true) ? method2() : method3();
}
}
How should I test shortcut method?
I know how to mock objects and test methods that use other object. Sample:
class Car{
public boolean start(){};
public boolean stop(){};
public boolean drive(int km){};
}
class CarAutoPilot(){
public boolean hasGotExternalDevicesAttached(){
//Hardware specific func and api calls
//check if gps is available
//check if speaker is on
//check if display is on
}
public boolean drive(Car car, int km){
//drive
boolean found = hasGotExternalDevicesAttached();
boolean start = c.start();
boolean drive = c.drive(km);
boolean stop = c.stop();
return (found && start && drive && stop) == true;
}
}
class CarAutoPilotTest(){
#Test
public void shouldDriveTenKm(){
Car carMock = EasyMock.Create(Car.class);
EasyMock.expect(carMock.start()).andReturns(true);
EasyMock.expect(carMock.drive()).andReturns(true);
EasyMock.expect(carMock.stop()).andReturns(true);
EasyMock.reply(carMock);
CarAutoPilot cap = new CarAutoPilot();
boolean result = cap.drive(cap,10);
Assert.assertTrue(result);
EasyMock.verify(carMock);
}
}
But what about hasGotExternalDevicesAttached() method? This is only sample not real scenario. How should I test drive method? Should I also mock hasGotExternalDevicesAttached function?
Can I mock class that is being tested?
I would create one test for each method. If you lower the complexity then it is much easier to test.
these should have one test each:
public boolean method1();
public String method2();
public String method3();
There is no need to test the last method since it calls your other methods, how ever, if that method changes (since im guessing its only a sample code) and it has more logic in it then you should have one test method for that as well.
When it comes to the hasGotExternalDevicesAttached() you should create a mocker for all external io calls that you cant test.
If you want to improve your skill within testing I would recommend that you read The Art of Unit Testing. This is in my opinion the best book for beginners to learn and study the art of unit testing.
You can create a subclass of CarAutoPilot in which you override hasGotExternalDevicesAttached(), and run the test with an instance of this subclass.
You can do it inline:
CarAutoPilot cap = new CarAutoPilot() {
public boolean hasGotExternalDevicesAttached(){
// return true or false depending on what you want to test
}
};
This way you can create a valid unit test for the rest of CarAutoPilot's behaviour.
You can call this a poor man's partial mock if you wish :-)
Yes you can, using the EasyMock Class Extension library. Look for "Partial mocking" in the documentation of EasyMock.
The idea is to mock only one (or some) of the methods of an object, and test the methods that depend on the mocked method.
Related
How to mock methods with void return type?
I implemented an observer pattern but I can't mock it with Mockito because I don't know how.
And I tried to find an example on the Internet but didn't succeed.
My class looks like this:
public class World {
List<Listener> listeners;
void addListener(Listener item) {
listeners.add(item);
}
void doAction(Action goal,Object obj) {
setState("i received");
goal.doAction(obj);
setState("i finished");
}
private string state;
//setter getter state
}
public class WorldTest implements Listener {
#Test public void word{
World w= mock(World.class);
w.addListener(this);
...
...
}
}
interface Listener {
void doAction();
}
The system is not triggered with mock.
I want to show the above-mentioned system state. And make assertions according to them.
Take a look at the Mockito API docs. As the linked document mentions (Point # 12) you can use any of the doThrow(),doAnswer(),doNothing(),doReturn() family of methods from Mockito framework to mock void methods.
For example,
Mockito.doThrow(new Exception()).when(instance).methodName();
or if you want to combine it with follow-up behavior,
Mockito.doThrow(new Exception()).doNothing().when(instance).methodName();
Presuming that you are looking at mocking the setter setState(String s) in the class World below is the code uses doAnswer method to mock the setState.
World mockWorld = mock(World.class);
doAnswer(new Answer<Void>() {
public Void answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
System.out.println("called with arguments: " + Arrays.toString(args));
return null;
}
}).when(mockWorld).setState(anyString());
I think I've found a simpler answer to that question, to call the real method for just one method (even if it has a void return) you can do this:
Mockito.doCallRealMethod().when(<objectInstance>).<method>();
<objectInstance>.<method>();
Or, you could call the real method for all methods of that class, doing this:
<Object> <objectInstance> = mock(<Object>.class, Mockito.CALLS_REAL_METHODS);
Adding to what #sateesh said, when you just want to mock a void method in order to prevent the test from calling it, you could use a Spy this way:
World world = new World();
World spy = Mockito.spy(world);
Mockito.doNothing().when(spy).methodToMock();
When you want to run your test, make sure you call the method in test on the spy object and not on the world object. For example:
assertEquals(0, spy.methodToTestThatShouldReturnZero());
The solution of so-called problem is to use a spy Mockito.spy(...) instead of a mock Mockito.mock(..).
Spy enables us to partial mocking. Mockito is good at this matter. Because you have class which is not complete, in this way you mock some required place in this class.
First of all: you should always import mockito static, this way the code will be much more readable (and intuitive):
import static org.mockito.Mockito.*;
For partial mocking and still keeping original functionality on the rest mockito offers "Spy".
You can use it as follows:
private World world = spy(new World());
To eliminate a method from being executed you could use something like this:
doNothing().when(someObject).someMethod(anyObject());
to give some custom behaviour to a method use "when" with an "thenReturn":
doReturn("something").when(this.world).someMethod(anyObject());
For more examples please find the excellent mockito samples in the doc.
How to mock void methods with mockito - there are two options:
doAnswer - If we want our mocked void method to do something (mock the behavior despite being void).
doThrow - Then there is Mockito.doThrow() if you want to throw an exception from the mocked void method.
Following is an example of how to use it (not an ideal usecase but just wanted to illustrate the basic usage).
#Test
public void testUpdate() {
doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
if (arguments != null && arguments.length > 1 && arguments[0] != null && arguments[1] != null) {
Customer customer = (Customer) arguments[0];
String email = (String) arguments[1];
customer.setEmail(email);
}
return null;
}
}).when(daoMock).updateEmail(any(Customer.class), any(String.class));
// calling the method under test
Customer customer = service.changeEmail("old#test.com", "new#test.com");
//some asserts
assertThat(customer, is(notNullValue()));
assertThat(customer.getEmail(), is(equalTo("new#test.com")));
}
#Test(expected = RuntimeException.class)
public void testUpdate_throwsException() {
doThrow(RuntimeException.class).when(daoMock).updateEmail(any(Customer.class), any(String.class));
// calling the method under test
Customer customer = service.changeEmail("old#test.com", "new#test.com");
}
}
You could find more details on how to mock and test void methods with Mockito in my post How to mock with Mockito (A comprehensive guide with examples)
In Java 8 this can be made a little cleaner, assuming you have a static import for org.mockito.Mockito.doAnswer:
doAnswer(i -> {
// Do stuff with i.getArguments() here
return null;
}).when(*mock*).*method*(*methodArguments*);
The return null; is important and without it the compile will fail with some fairly obscure errors as it won't be able to find a suitable override for doAnswer.
For example an ExecutorService that just immediately executes any Runnable passed to execute() could be implemented using:
doAnswer(i -> {
((Runnable) i.getArguments()[0]).run();
return null;
}).when(executor).execute(any());
Adding another answer to the bunch (no pun intended)...
You do need to call the doAnswer method if you can't\don't want to use spy's. However, you don't necessarily need to roll your own Answer. There are several default implementations. Notably, CallsRealMethods.
In practice, it looks something like this:
doAnswer(new CallsRealMethods()).when(mock)
.voidMethod(any(SomeParamClass.class));
Or:
doAnswer(Answers.CALLS_REAL_METHODS.get()).when(mock)
.voidMethod(any(SomeParamClass.class));
I think your problems are due to your test structure. I've found it difficult to mix mocking with the traditional method of implementing interfaces in the test class (as you've done here).
If you implement the listener as a Mock you can then verify the interaction.
Listener listener = mock(Listener.class);
w.addListener(listener);
world.doAction(..);
verify(listener).doAction();
This should satisfy you that the 'World' is doing the right thing.
If you need to do some operations in the mocked void method, and you need to manipulate the argument that sent to void method; you can combine Mockito.doAnswer with ArgumentCaptor.capture method.
Let's say you have SpaceService that autowires a GalaxyService, which has a void method called someServiceMethod.
You want to write test for one of your method in SpaceService that calls GalaxyService's void method. Your planet is also generated inside SpaceService. So you don't have any chance to mock that.
Here is your sample SpaceService class that you want to write tests for.
class SpaceService {
#Autowired
private GalaxyService galaxyService;
public Date someCoolSpaceServiceMethod() {
// does something
Planet planet = new World();
galaxyService.someServiceMethod(planet); //Planet updated in this method.
return planet.getCurrentTime();
}
}
The GalaxyService.someServiceMethod method expects a planet argument. Does some stuff in the method. See :
GalaxyService {
public void someServiceMethod(Planet planet) {
//do fancy stuff here. about solar system etc.
planet.setTime(someCalculatedTime); // the thing that we want to test.
// some more stuff.
}
}
And you want to test this feature.
Here is an example :
ArgumentCaptor<World> worldCaptor = ArgumentCaptor.forClass(World.class);
Date testDate = new Date();
Mockito.doAnswer(mocked-> {
World capturedWorld = worldCaptor.getValue();
world.updateTime(testDate);
return null;
}).when(galaxyService.someServiceMethod(worldCaptor.capture());
Date result = spaceService.someCoolSpaceServiceMethod();
assertEquals(result, testDate);
In your example you should mock Listener item and use Mockito.verify to check interactions with it
I need to mock the constant variable in order to test one of my method. How can I do it with Mokito and Junit.
#Component( "mybean" )
#org.springframework.context.annotation.Scope( value="session" )
public class MyBean {
Public void methodToBeTested() {
if (!AppConst.SOME_CONST.equals(obj.getCostCode())) {
// some logic
}
}
}
AppConst class
#Configuration
public class AppConst
{
public static String SOME_CONST;
public static String HOST_URL;
#PostConstruct
public void postConstruct()
{
SOME_CONST = "My Code";
HOST_URL = "Some URL";
}
}
So, from my junit test class, how can I mock the AppConst and it's variables? Now, when I run it, i hit a nullpointer error.
Can this be done with powermock? if yes please give some sample
Mockito version I use.
compile "org.mockito:mockito-all:1.9.5"
compile "org.powermock:powermock-mockito-release-full:1.6.1"
Instead of mocking there would be another solution to be able to test it:
public void methodToBeTested(SomeObject obj) {
performLogic(AppConst.SOME_CONST, obj);
}
boolean performLogic(String check, SomeObject testObj) {
if (!check.equals(obj.getCostCode())) {
// some logic
return true;
}
return false;
}
That way you can test two things, both combined show you that your code works as intended:
public void testMethodToBeTested() {
MyBean mb = new MyBean() {
#Override
void performLogic(String check, SomeObject testObj) {
assertSame("check constant is passed", AppConst.SOME_CONST, check);
}
}
mb.methodToBeTested(new SomeObject());
mb = new MyBean();
SomeObject so = createSomeTestObject("My Code"); // not the actual constant but an equal String
assertFalse("check some logic not occurred", mb.performLogic("My Code", so));
so = createSomeTestObject("Not the constant");
assertFalse("check some logic not occurred", mb.performLogic("Not the constant", so));
assertTrue("check some logic occurred", mb.performLogic("My Code", so));
// additional tests covering the actual logic
}
Another solution could be putting the condition of the if-statement into its own method, e.g. shouldLogicOccurr(String check) and test that method individually.
In other words: Sometimes it's necessary to refactor your code to make tests easier or sometimes even possible at all. A good side effect is the next time you implement something you already have testability in mind and create your code suitable for this in the first place.
Mocking is a good way to get things under test that use third party libraries that can't be changed and have too many dependencies to be set up but if you end up using that for your own code you've got a design issue.
Suppose I have a code like below
public boolean checkForecastIfCityRaining(String name){
result = WeatherAPICallToSomeVendor(name)
if(result = rain)return true; else return false;
}
How would I unit test if the result data will change depending
on what the API vendor is providing?
Would i mock a fixed result of every scenario and then unit test
it like so?
A UNIT test should really only test a single method at a time (Isolate other functionality that might be invoked by that method). My current group might achieve that by writing our function like this:
public class WeatherCheck
{
private ForecastService fs;
public WeatherCheck(ForecastService fs)
{
forecastService = fs;
}
public boolean checkForecastIfCityRaining(String name){
result = forecastService.weatherAPICallToSomeVendor(name)
if(result = rain)return true; else return false;
}
This would allow us to pass a mock forecast service into the constructor. Dependency Injection would be better, but we don't do that yet.
Note: We differentiate between a Unit test and an Integration test. We still might write our Integration tests with Junit, but they have more of a tendency to go out and actually poke the service--this can give you advance warning of a failure. So you might write an integration test for ForecastService that simply calls the weatherAPICallToSomeVendor method of ForecastService and ensures a non-error result (Perhaps no exceptions or doesn't return null...).
I think the function needs to be rewritten as this:
public boolean checkForecastInCityCondition(String city, String condition){
result = WeatherAPICallToSomeVendor(city)
return result == condition;
}
Now you gain the advantage of exposing clients to care about arbitrary conditions and you can enhance with a new API as needed. From a testing perspective you can now safely write tests like this:
public void testRainingInLancaster() throws Exception{
//your code here
}
public void testSnowInRedding() throws Exception{
//your code here
}
And you can determine which pieces need to be mocked for testing.
Im writing unit test using testng and mockito.
Im normally practice to call one method few times inside same test method by using different values / condition to check all scenarios.
Please dont think about the logic, and design i have provided. this is just sample for clear what actually i want to make.
Review code below.
public class Human {
private String name;
private boolean parent;
private List<Human> childs = new ArrayList<>();
public String getName() {
return name;
}
public boolean isParent() {
return parent;
}
public void setParent(boolean parent) {
this.parent = parent;
}
public void addChild(List<Human> childs) {
this.childs = childs;
}
public List<Human> getChilds() {
return childs;
}
}
public class Validator {
public boolean isParent(Human human) {
if (null == human) {
return false;
}
if (human.isParent()) {
return true;
}
if (human.getChilds().size() > 0) {
return true;
}
return false;
}
}
Im writing test case for Validator isParent method by using mockito.
public class ValidatorTest {
public void testIsParent() throws Exception {
Validator validator = Mockito.spy(new Validator());
Human human = Mockito.mock(Human.class);
Mockito.when(human.isParent()).thenReturn(false);
boolean isParent = validator.isParent(human);
Mockito.verify(human).getChilds();
Mockito.when(human.isParent()).thenReturn(true);
isParent = validator.isParent(human);
Mockito.verify(human).getChilds();
}
In here i want to verify that getChilds() never call for second method call to validator.isParent(human) because mocked human set to return true when call human.isParent();
I used Mockito.verifyZeroInteractions() but it says fail
As i understand Mockito.verifyZeroInteractions() check through all test. not only for particular method call.
I want to know is there some way to verify that method is not call for some cases and method call for same cases within same test method.
Or should i should practice test one scenario in one test method.
It's a good practice to have "one scenario per one one test method" (see How many unit tests should I write per function/method? )
Technically it's still possible to reset mocks with Mockito.reset(...), but this what official documentation says about it:
Smart Mockito users hardly use this feature because they know it could be a sign of poor tests.
Normally, you don't need to reset your mocks, just create new mocks for each test method.
Instead of reset() please consider writing simple, small and focused test methods over lengthy, over-specified tests. First potential code smell is reset() in the middle of the test method. This probably means you're testing too much. Follow the whisper of your test methods: "Please keep us small & focused on single behavior".
See https://static.javadoc.io/org.mockito/mockito-core/2.9.0/org/mockito/Mockito.html#17
The verify method can accept a second argument where you can specify how many times the method has been called. You can use this to say the method was never called, called once, twice etc.
For example:
import static org.mockito.Mockito.never;
...
public void testIsParent() throws Exception {
Validator validator = Mockito.spy(new Validator());
Human human = Mockito.mock(Human.class);
Mockito.when(human.isParent()).thenReturn(false);
boolean isParent = validator.isParent(human);
Mockito.verify(human).getChilds();
Mockito.when(human.isParent()).thenReturn(true);
isParent = validator.isParent(human);
Mockito.verify(human, never()).getChilds();
}
The documentation for this is here: http://static.javadoc.io/org.mockito/mockito-core/2.9.0/org/mockito/Mockito.html#4
I want to point out that this question seriously abuses mocking, for testing something that can easily and cleanly be tested without any mocks.
This is what the tests should look like:
public class ValidatorTest {
final Validator sut = new Validator();
#Test
public void checkThatNoHumanIsNotAParent() {
boolean isParent = sut.isParent(null);
assertFalse(isParent);
}
#Test
public void checkHumanThatIsNotAParent() {
Human notAParent = new Human();
boolean isParent = sut.isParent(notAParent);
assertFalse(isParent);
}
#Test
public void checkParentHumanWithNoChildIsAParent() {
Human parentWithNoChildren = new Human();
parentWithNoChildren.setParent(true);
boolean isParent = sut.isParent(parentWithNoChildren);
assertTrue(isParent);
}
#Test
public void checkHumanNotMarkedAsParentButWithChildIsAParent() {
Human humanWithChildren = new Human();
Human child = new Human();
humanWithChildren.addChild(child);
boolean isParent = sut.isParent(humanWithChildren);
assertTrue(isParent);
}
}
These tests completelly exercise all four scenarios. They are clearly much better than a version that uses mocking. Finally, note that Mockito's documentation (in the page on how to write good tests) also says that value objects (such as Human) should not be mocked.
I'm trying to write a unit test for a function that has a condition for wifi state. When the wifi state is disconnected, the function returns with false, but I want to simulate a scenario when the wifi state is connected. How do I go about it? Should I make a setter for the state variable? Isn't that a bad approach?
The function I want to test:
public boolean performSomething() {
if (WIFI_STATE != "connected") {
return false;
}else{
....
}
}
I want to test the else part of the function above, but as you may have guessed, the function executes the if condition, and returns false because WIFI_STATE is "disconnected"
Without seeing any of your code, make sure your class uses a WifiState constructor parameter or injection (or something similar). In your test you can then provide a mock for this object and set the state accordingly to your testing needs.
Two approaches that I can think of:
1: Define a sensor's state capturing class say WifiStatus, which your production code initializes automatically through a static initializer.
For testing, you can load a dummy WifiStatus class though a test initializer or change the value of WifiStatus through instrumentation.
2: Use WifiStatus as a interface and then mock it for dependency injection. This approach is more common.
public interface WifiStatus{
boolean isConnected();//
}
public class Performer{
WifiStatus wifiStatusProvider;
public Performer(WifiStatus stateProvider){
this.wifiStatusProvider = stateProvider;
}
public boolean performSomething() {
//if (WIFI_STATE != "connected") {
if (wifiStatusProvider.isConnected() != true) {
return false;
}else{
....
}
}
}
For test class, you use as follows:
public class PerformerTest{
#Test
public void verifyPerformSomething(){
WifiStatus dummyWifiStatus = mock(WifiStatus.class);
doReturn(true).when(dummyWifiStatus).isConnected();
new Performer(dummyWifiStatus).performSomething();
}
}
Assuming you are talking about "Local Unit Tests" and not "Instrumented Unit Tests", you can use Robolectric: http://robolectric.org
http://robolectric.org/javadoc/3.0/org/robolectric/shadows/ShadowWifiManager.html
https://github.com/robolectric/robolectric/blob/master/robolectric/src/test/java/org/robolectric/shadows/ShadowWifiManagerTest.java
Local Unit Tests:
https://developer.android.com/training/testing/unit-testing/instrumented-unit-tests.html
Instrumented Unit Tests:
https://developer.android.com/training/testing/unit-testing/instrumented-unit-tests.html
Well, for testing, you must be sure for your input how your output looks like because you need to compare them. Make the boolean value of wifi state is injected from outside, so you can mock it how you like. For example:
public boolean method(boolean wifiState){
return !wifiState;
}
So now you can be sure that if your parameter is false you will got true and vice versa so you can mock that param and make your tests.
Chiming in with a code-based answer based on john16384's answer. You mention that the state is set with other functions within the same class, assuming those methods are public I propose something like this (assuming WifiChecker is your class):
private WifiChecker wifiChecker;
#Before public void setUp() {
wifiChecker = new WifiChecker();
}
#Test public void testWifiConnected() {
wifiChecker.setConnected()
assertTrue(wifiChecker.performSomething());
}
#Test public void testWifiDisconnected() {
wifiChecker.setDisconnected()
assertFalse(wifiChecker.performSomething());
}