How do you mock a singleton dependency in JMockit? - jmockit

I'm working on some automated unit and integration tests for a robot. As you could imagine, a robot has a lot of sensor objects and such that would need mocking during testing.
One of the dependencies is a singleton designed not to be instantiated by anything but itself. As I understood it (I'm new to JMockit), once a class is annotated with #Mocked all of its methods and constructors are mocked. JMockit Documentation:
There are three different mocking annotations we can use when declaring mock fields and parameters: #Mocked, which will mock all methods and constructors on all existing and future instances of a mocked class
However I'm noticing (via the usage of a breakpoint) that the real class' constructor is being called and failing to access a sensor, causing the tests to fail.
Here is the relevant part of the singleton I'm trying to mock. Note that I cannot modify this class:
public class DriverStation() {
// This line in particular is an issue.
private static DriverStation currentInstance = new DriverStation();
public static DriverStation getInstance() {
return DriverStation.instance;
}
private DriverStation() {
// This constructor cannot be called during tests.
}
}
And here is my test code:
public class BlingControllerTest {
#Mocked
private DriverStation station;
#Tested
private BlingController blingController;
/**
* Tests getting the robot's operation period while not in a real match.
*/
#Test
public void testGetOperationPeriodDuringRealMatch(#Mocked DriverStation station) {
new Expectations(DriverStation.class) {{
DriverStation.getInstance();
result = station;
station.isFMSAttached();
result = true;
station.isAutonomous();
returns(true, false);
}};
}
}
Full source also available on GitHub
I should also mention that for some reason calling the singleton's constructor locally during tests isn't a problem, but when the tests are run on travis-ci it is a problem.
Stacktrace from running on travis-ci:
ca.team2706.frc.robot.commands.bling.BlingControllerTest > testGetOperationPeriodDuringRealMatch STANDARD_ERROR
java.io.IOException: wpiHaljni could not be loaded from path or an embedded resource.
attempted to load for platform /linux/x86-64/
at edu.wpi.first.wpiutil.RuntimeLoader.loadLibrary(RuntimeLoader.java:79)
at edu.wpi.first.hal.JNIWrapper.<clinit>(JNIWrapper.java:25)
at edu.wpi.first.wpilibj.DriverStation.<init>(DriverStation.java:194)
at edu.wpi.first.wpilibj.DriverStation.<clinit>(DriverStation.java:132)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at mockit.internal.state.TestRun.ensureThatClassIsInitialized(TestRun.java:138)
at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineType(BaseTypeRedefinition.java:65)
at mockit.internal.expectations.mocking.TypeRedefinition.redefineType(TypeRedefinition.java:28)
at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldType(FieldTypeRedefinitions.java:78)
at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldType(FieldTypeRedefinitions.java:65)
at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldTypes(FieldTypeRedefinitions.java:53)
at mockit.internal.expectations.mocking.FieldTypeRedefinitions.<init>(FieldTypeRedefinitions.java:33)
at mockit.integration.TestRunnerDecorator.handleMockFieldsForWholeTestClass(TestRunnerDecorator.java:142)
at mockit.integration.TestRunnerDecorator.updateTestClassState(TestRunnerDecorator.java:40)
Any and all help is appreciated.

Related

How did TestNg annotation mentioned in one class get executed from another from another class?

While learning Testng on Udemy, I come across a code which I am unable to understand. Instructor has created class named "testcore" where he defined #BeforeMethod/#aftermethod.Later he created another class named "LoginTest" where he wrote actual test with #test. He extended testcore class in loginTest to get variable initiated in testcore class. When he ran loginTest then #BeforeMethod/#aftermethod also ran with this. How did these two method ran along with #test when these methods are in different class.
here are both codes:
public class testcore {
public static Properties config = new Properties();
public static Properties obj = new Properties();
public static Xls_Reader xls = null;
public static WebDriver driver;//=null;
#BeforeMethod
public void init() throws Exception{
if(driver==null) {
// Loading Config Properties File
File Config_f = new File(System.getProperty("user.dir")+"\\src\\dd_Properties\\config.properties");
FileInputStream fs = new FileInputStream(Config_f);
config.load(fs);
// Loading Object Properties File
File Obj_f = new File(System.getProperty("user.dir")+"\\src\\dd_Properties\\Object.properties");
fs = new FileInputStream(Obj_f);
obj.load(fs);
//Loading xlsx file
xls = new Xls_Reader(System.getProperty("user.dir")+"\\src\\dd_Properties\\Data.xlsx");
System.out.println(config.getProperty("browerName"));
if(config.getProperty("browerName").equalsIgnoreCase("Firefox")) {
driver = new FirefoxDriver();
}
else if(config.getProperty("browerName").equalsIgnoreCase("Chrome")) {
driver = new ChromeDriver();
}
else {
throw new Exception("Wrong/No Browswer sepcified");
}
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
}
#AfterMethod
public void quitdriver() throws EmailException {
driver.quit();
//monitoringMail.Sendmail();
}
Here are LoginTest class:
public class LoginTest extends testcore {
#Test
public void doLogin() {
driver.findElement(By.xpath(obj.getProperty("LoginBtn"))).click();
driver.findElement(By.xpath(obj.getProperty("username"))).sendKeys();
driver.findElement(By.xpath(obj.getProperty("password"))).sendKeys();
}
1) How did these two method ran along with #test.
First of all LoginTest extends the testcore .
Due to this we can inherit the method of testcore in our LoginTest class.
2) When he ran loginTest then #BeforeMethod/#aftermethod also ran with this.
Please refer below details
Configuration information for a TestNG class:
#BeforeSuite: The annotated method will be run before all tests in this suite have run.
#AfterSuite: The annotated method will be run after all tests in this suite have run.
#BeforeTest: The annotated method will be run before any test method belonging to the classes inside the <test> tag is run.
#AfterTest: The annotated method will be run after all the test methods belonging to the classes inside the <test> tag have run.
#BeforeGroups: The list of groups that this configuration method will run before. This method is guaranteed to run shortly before the first test method that belongs to any of these groups is invoked.
#AfterGroups: The list of groups that this configuration method will run after. This method is guaranteed to run shortly after the last test method that belongs to any of these groups is invoked.
#BeforeClass: The annotated method will be run before the first test method in the current class is invoked.
#AfterClass: The annotated method will be run after all the test methods in the current class have been run.
#BeforeMethod: The annotated method will be run before each test method.
#AfterMethod: The annotated method will be run after each test method.
It's very simple inheritance related question. When you have extended testcore class in LoginTest class all the methods and data member available in parent will be available to child class including methods annotated with #Before Method etc.
I think you are confused due to miss concept regarding the way TestNG run a program. There are different different way to run a testNG annotated program to get executed and among them XML is a way. So don't get get confuse that all class, methods need to include in that xml. You just need an entry point only and rest will call accordingly.

When should we use #InjectMocks?

I have read through a lot of discussion about #Mock & #InjectMocks and still could not find what are the suitable or necessary cases to use #InjectMocks. In fact, I am not sure about what would happen when we use #InjectMocks.
Consider the following example,
public class User {
private String user_name;
private int user_id;
public User(int user_id) {
this.user_id = user_id;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
}
public interface UserDao {
public List<User> getUserList();
}
public class UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public List<User> getUserList() {
return userDao.getUserList();
}
}
This is my test class
#RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
private UserService service = new UserService();
#Mock
private UserDao dao;
#Test
public void testGetUserList() {
service.setUserDao(dao);
// mock the return value of the mock object
List<User> mockResult = Arrays.asList(new User(101),new User(102),new User(103));
when(dao.getUserList()).thenReturn(mockResult);
// check return value is same as mocked value
assertEquals(service.getUserList(),mockResult);
// verify the getUserList() function is called
verify(dao).getUserList();
}
}
The test run successfully with no errors.
Consider another approach using #InjectMock annotation.
#RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
#InjectMocks
private UserService service;
#Mock
private UserDao dao;
#Test
public void testGetUserList() {
service.setUserDao(dao);
// mock the return value of the mock object
List<User> mockResult = Arrays.asList(new User(101),new User(102),new User(103));
when(dao.getUserList()).thenReturn(mockResult);
// check return value is same as mocked value
assertEquals(service.getUserList(),mockResult);
// verify the getUserList() function is called
verify(dao).getUserList();
}
}
This works equally well. So, which way is better? Any best practice?
Btw, I am using Junit 4.8.1 and Mockito 1.9.5
Your actual question can't be answered without you providing further code (the code you are showing does not explain the results you claim to observe).
Regarding the underlying question: you probably should not use #InjectMocks; one of its core problems is: if injecting fails, Mockito does not report an error to you.
In other words: you have passing unit tests, and some internal detail about a field changes ... and your unit tests break; but you have no idea why ... because the mocking framework doesn't tell you that the "initial" step of pushing a mock into the class under test is all of a sudden failing. See here for further reading.
But to be clear here: in the end, this almost a pure style question. People used to #InjectMocks will love it; other people do object it. Meaning: there is no clear evidence whether you should use this concept. Instead: you study the concept, you understand the concept, and then you (and the team working with you) make a conscious decision whether you want to use this annotation, or not.
Edit: I think I get your problem now. The idea of #InjectMocks is to inject a mocked object into some object under test.
But: you are doing that manually in both cases:
service.setUserDao(dao);
Meaning: if injecting works correctly (and there isn't a problem that isn't reported by Mockito) then your example that uses that annotation should also work when you remove that one line. Whereas the testcase that doesn't have #InjectMocks should fail without that line!
In other words: your testcases are both passing because your code does a "manual inject"!
When should we use #InjectMocks?
IHMO : we should not use it.
That favors so many design issues that I would like to add my POV on the question.
Here is relevant information from the javadoc (emphasis is not mine) :
Mark a field on which injection should be performed.
Allows shorthand mock and spy injection.
Minimizes repetitive mock and spy injection.
Mockito will try to inject mocks only either by constructor injection,
setter injection, or property injection in order and as described
below. If any of the following strategy fail, then Mockito won't
report failure; i.e. you will have to provide dependencies yourself.
...
Mockito is not an dependency injection framework,
In two words :
Advantage : you write less code to setup your mock dependencies.
Drawback : no failure if some mocks were not be set in the object under test.
IHMO the advantage hides also another drawback still more serious.
About the advantage :
Mockito uses constructor/setter/reflection to set the mocks in the object under test. The problem is that it is up to you to decide the way to set your fields : mockito will try one after the other way.
The setter way is often very verbose and provides mutability of the dependencies. So developers don't use it frequently. It makes sense.
The constructor way to set the bean dependencies requires to keep a good design with a decent number of dependencies : not more than 4 or 5 in general.
It demands strong design exigencies.
At last, the reflection way is the most easy : few code to write and no mutability of the dependencies.
The reflection way being the simplest from the lambda developer PVO, I saw many teams not aware of the consequences of reflection to specify dependencies and abuse of the reflection way in their Mockito tests but also in their design since finally InjectMocks allows to cope with it in a someway.
You may consider it fine to not finish with a class that declares 30 setters as dependencies or a constructor with 30 arguments but that has also a strong drawback : it favors bad smells such as dependency field hiding and declaration of many dependencies in as field instances of the class. As a result your class is complex, bloat, hard to read, hard to test and error prone to maintain.
The real thing is that in the very most of cases, the right solution is the constructor injection that promotes decent class responsibility and so good maintainability and testability of that.
About the drawback :
Mock injection doesn't work as the dependency injection of IOCs.
The javadoc states itself :
Mockito is not an dependency injection framework,
IOC and DI framework are able and by default consider dependencies as required. So any missing dependency will provoke a fast-fail error at the startup.
It prevents so many headaches and makes you win a precious time.
While Mockito injection will silently ignore the mocks that were not managed to be injected. It is so up to you to guess the error cause.
Finding the issue cause is sometimes complex because you don't have any clue from Mockito and that all is done by reflection by Mockito.
Using #InjectMocks injects the mocked objects as dependencies to the created object(The object marked by #InjectMocks). Creating an object using constructor will defy the purpose since the mocked objects are not injected and hence all the external calls from SUT takes place on concrete objects.Try to avoid creating SUT object by constructor call.

General Fixture Setup with PowerMockito and #BeforeClass

I have a test where I configure some general fixtures however after using PowerMockRule the static variables which I configure in my #BeforeClass method reset to null. This causes the following test to fail however if you remove PowerMockRule it passes.
public class Test
{
#Rule
public PowerMockRule rule = new PowerMockRule();
private static String MyString;
#BeforeClass
public static void setupClass() throws Exception
{
MyString = "FOO";
}
#org.junit.Test
public void test() throws Exception
{
assertEquals("FOO", MyString);
}
}
I have the answer, but you are not going to like it.
Short answer:it looks like a defect in PowerMock, so create a issue in our bug tracker
Long answer: As you may know the PowerMock to be able mock static, private and so on loads classes by custom class loader and modified byte code. Then #PowerMockRunneris used then PowerMock can control loading a test class and the test class is also loaded by custom class loader. In case if another jUnitRunner runs test and the PowerMockRuleis used, then the test class and all other classes that is needed for test are loaded with standard class loader. PowerMock reloads all these classes either by using deep coping with serializing/deserializing or by using objenesis. So as class is reloaded all static fields which was initialised are null.
I've briefly checked code and I haven't found test for your cases and that we processed #BeforeClass, so create a issue in our bug tracker and I'll check it deeply.
By the way, please, also point which version do you use and which dependencies do you use.

How JUnit TestCase functionality actually works?

I have a code like this:
public class MyTest extends TestCase {
private MyObject mObject1;
private MyObject mObject2;
...
#Override
public void setUp() throws Exception {
super.setUp();
}
public void testSomething() {
mObject1 = new MyObject();
mObject2 = new MyObject();
}
public void testSomething2() {
// Here I can't access the previously created objects mObject1 and
// mObject2, because they are again null.
// Why is that, if *my* setUp() method doesn't touch them?
}
My guess is that JUnit instantiates the class again every time. Can someone please explain me the workflow?
Thanks.
JUnit will instantiate the class (MyTest) once per test and then execute the methods
setUp()
testXXX()
tearDown()
until it runs all the methods that start with test and don't receive any parameters. So in your example, Junit will instantiate MyTest twice. You can read more about this in the JUnit documentation.
Bear in mind that this is the old way of writing tests. From Junit 4 (I think) the preferred way is to use annotations. You can check the annotations documentation here.
As a side note, NUnit, reuses the instance of the test, so in the same scenario, it would only instantiate MyTest once.
JUnit will instantiate this class once per test method, so only once in the code above, but try it again with two test methods and you will see it instantiated twice. If you want to save some state in fields without having to use statics, take a look at TestNG, which reuses the same instance for all test methods.

wicket and AtUnit

I've started playing with Wicket and I've chosen Guice as dependency injection framework. Now I'm trying to learn how to write a unit test for a WebPage object.
I googled a bit and I've found this post but it mentioned AtUnit so I decided to give it a try.
My WebPage class looks like this
public class MyWebPage extends WebPage
{
#Inject MyService service;
public MyWebPage()
{
//here I build my components and use injected object.
service.get(id);
....
}
}
I created mock to replace any production MyServiceImpl with it and I guess that Guice in hand with AtUnit should inject it.
Now the problems are:
AtUnit expects that I mark target object with #Unit - that is all right as I can pass already created object to WicketTester
#Unit MyWebPage page = new MyWebPage();
wicketTester.startPage(page);
but usually I would call startPage with class name.
I think AtUnit expects as well that a target object is market with #Inject so AtUnit can create and manage it - but I get an org.apache.wicket.WicketRuntimeException: There is no application attached to current thread main. Can I instruct AtUnit to use application from wicketTester?
Because I don't use #Inject at MyWebPage (I think) all object that should be injected by Guice are null (in my example the service reference is null)
I really can't find anything about AtUnit inside Wicket environment. Am I doing something wrong, am I missing something?
I don't know AtUnit but I use wicket with guice and TestNG. I imagine that AtUnit should work the same way. The important point is the creation of the web application with the use of guice.
Here how I bind all this stuff together for my tests.
I have an abstract base class for all my tests:
public abstract class TesterWicket<T extends Component> {
#BeforeClass
public void buildMockedTester() {
System.out.println("TesterWww.buildMockedTester");
injector = Guice.createInjector(buildModules());
CoachWebApplicationFactory instance =
injector.getInstance(CoachWebApplicationFactory.class);
WebApplication application = instance.buildWebApplication();
tester = new WicketTester(application);
}
protected abstract List<Module> buildModules();
The initialization is done for every test class. The subclass defines the necessary modules for the test in the buildModules method.
In my IWebApplicationFactory I add the GuiceComponentInjector. That way, after all component instantiation, the fields annotated with #Inject are filled by Guice:
public class CoachWebApplicationFactory implements IWebApplicationFactory {
private static Logger LOG = LoggerFactory.getLogger(CoachWebApplicationFactory.class);
private final Injector injector;
#Inject
public CoachWebApplicationFactory(Injector injector) {
this.injector = injector;
}
public WebApplication createApplication(WicketFilter filter) {
WebApplication app = injector.getInstance(WebApplication.class);
Application.set(app);
app.addComponentInstantiationListener(new GuiceComponentInjector(app, injector));
return app;
}
}