JukitoRunner, bind mock of final class - mockito

How to bind mock of final class in Jukito ?
For example :
public final class SomeFinalClass(){
public SomeFinalClass(String someString){
}
}
//Testing class
#Runwith(JukitoRunner.class)
public class TestingClass(){
#Inject
private SomeFinalClass someFinalClassMock;
public static class TestModule extends JukitoModule {
#Override
protected void configureTest() {
// bind(SomeClient.class).in(TestSingleton.class);
}
#Provides
public SomeFinalClass getSomkeFinalClass() {
return Mokito.mock(SomeFinalClass.class); //throws error
}
}
}
Is there a way i can use PowerMockito with JukitoRunner ?

You can mock a final class if you're using Mockito 2. From Mockito 2 Wiki:
Mocking of final classes and methods is an incubating, opt-in feature. It uses a combination of Java agent instrumentation and subclassing in order to enable mockability of these types. As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line: mock-maker-inline.
After you created this file, Mockito will automatically use this new engine and one can do :
final class FinalClass {
final String finalMethod() { return "something"; }
}
FinalClass concrete = new FinalClass();
FinalClass mock = mock(FinalClass.class);
given(mock.finalMethod()).willReturn("not anymore");
assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());

Related

Mockito: How to test a class's void method?

Unit test noob here.
I have three classes: Db1Dao, Db2Dao, ExecuteClass where Db1Dao, Db2Dao are database access objects for two different databases. My goal is to fetch some data from db1 using Db1Dao and run executeClass.execute() to "put" the processed data into db2 using Db2Dao.
My ExecuteClass looks like this:
class ExecuteClass {
private Db1Dao db1Dao;
private Db2Dao db2Dao;
public void execute() {
...
List<String> listOfString = getExternalData(someParam);
List<Metadata> metadatum = db1Dao.get(someInputs);
... I do something to generate a list of new class `A` based on listOfString & metadatum ...
try {
db2Dao.put(listOfA);
} catch (PutException e){
...
}
}
public List<String> getExternalData(SomeClass someParam){
... do something
return listOfString;
}
}
Now I want to test:
Given a specific listOfString (returned by getExternalData) and a specific metadatum (returned by db1Dao.get):
Will I get the desired listOfA?
Am I able to call db2Dao.put and its input parameter is listOfA?
Particularly, I have hard-coded sample listOfString and metadatum and desired listOfA (and they will be passed via an object MockData, see the following code) but I don't know how to write the test using Mockito. The following is a test class I wrote but it does not work:
class TestClass extends BaseTest {
#Mock
private Db1Dao db1Dao;
#Mock
private Db2Dao db2Dao;
private ExecuteClass executeClass;
#BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
executeClass = new ExecuteClass(db1Dao, db2Dao);
}
#ParameterizedTest
#MethodSource("MockDataProvider")
public void executeClassTest(final MockData mockData) throws PutException {
Mockito.when(db1Dao.get(Mockito.any(), ...))
.thenReturn(mockData.getMetadatum());
ExecuteClass executeClassSpy = Mockito.spy(executeClass);
Mockito.when(executeClassSpy.getExternalData(Mockito.any()))
.thenReturn(mockData.getListOfString());
executeClassSpy.execute();
// executeClass.execute(); not working neither...
List<A> listOfA = mockData.getDesiredListOfA();
Mockito.verify(db2Dao).put(listOfA);
}
}
Could anyone please let me know? Thank you in advance!!
You should not create a spy of the same class you want to test. Instead, try to write a unit test for the smallest amount of code (e.g. a public method) and mock every external operator (in your case Db1Dao and Db2Dao).
If testing a public method involves calling another public method of the same class, make sure to mock everything inside the other public method (in your case getExternalData). Otherwise, this other public method might be a good candidate for an extra class to have clear separation of concerns.
So, remove the ExecuteClass executeClassSpy = Mockito.spy(executeClass); and make sure you setup everything with Mockito what's called within getExternalData.
To now actually, verify that Db2Dao was called with the correct parameter, either use your current approach with verifying the payload. But here it's important to 100% create the same data structure you get while executing your application code.
Another solution would be to use Mockito's #Captor. This allows you to capture the value of why verifying the invocation of a mock. Later on, you can also write assertions on the captured value:
#Captor
private ArgumentCaptor<ClassOfListOfA> argumentCaptor;
#Test
public void yourTest() {
Mockito.verify(db2Dao).put(argumentCaptor.capture());
assertEquals("StringValue", argumentCaptur.getValue().getWhateverGetterYouHave);
}
The following code worked for me.
I partially accepted #rieckpil's answer. I used #Captor which is very handy.
The reason I had to mock getExternalData() is because its implementation is still a "TODO".
class TestClass extends BaseTest {
#Mock
private Db1Dao db1Dao;
#Mock
private Db2Dao db2Dao;
#Captor
private ArgumentCaptor<List<A>> argumentCaptor;
private ExecuteClass executeClass;
#BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
executeClass = new ExecuteClass(db1Dao, db2Dao);
}
#ParameterizedTest
#MethodSource("MockDataProvider")
public void executeClassTest(final MockData mockData) throws PutException {
Mockito.when(db1Dao.get(Mockito.any(), ...))
.thenReturn(mockData.getMetadatum());
ExecuteClass executeClassSpy = Mockito.spy(executeClass);
Mockito.when(executeClassSpy.getExternalData(Mockito.any()))
.thenReturn(mockData.getListOfString());
executeClassSpy.execute();
List<A> listOfA = mockData.getDesiredListOfA();
Mockito.verify(db2Dao).put(argumentCaptor.capture());
assertEquals(listOfA, argumentCaptor.getValue());
}
}

thenReturn not returning expected values

#Component
public class RefValidator implements Component {
#Autowired
private Repository repository;
public void validate(Context context) {
Txn txn = context.getTxn();
if (Objects.nonNull(txn) && !StringUtils.isEmpty(txn.getReferenceNumber())){
if(txn.getId() == 0){
boolean isRealmIdAndReferenceNumberExists = repository.isRefNumberExistsInSale(txn.getRealmId(), txn.getReferenceNumber());
if(isRealmIdAndReferenceNumberExists){
throw new Exception();
}
}
}
}
}
I have a class as above and want to test it using mockito. I am doing #INjectMock for RefValidator and #Mock on Repository but when I do
Mockito
.when(repository.isRefNumberExistsInSale(Mockito.anyString(),Mockito.anyString()))
.thenReturn(true);
thenReturn doesn't return true.
It's kinda hard to define what's the problem because you haven't provided your test class. But it looks like your annotations are not being processed while running a test suit.
Try one of the following:
Add #RunWith(MockitoJUnitRunner.class) above your test class
Add MockitoAnnotations.initMocks(this); inside setup method (which is annotated with #Before)
See the 2nd section of this article for help.

How to mock System.getenv() in JUnit [Powermock + Parameterized]

How to mock "System.getenv("...")" in JUnit.
Currently I am doing:
#RunWith(Parameterized.class)
#PowerMockRunnerDelegate(PowerMockRunner.class)
#PrepareForTest(System.class)
public class TestClass extends BaseTest {
public TestClass(String testCase) {
this.testCase = testCase;
}
#Before
#Override
public final void initTable() throws Throwable {
super.initTable();
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getenv("ENV_VAR1")).thenReturn("1234");
}
...
}
I am using both PowerMock and Parameterizedrunner.
I am getting below exception for line:
PowerMockito.when(System.getenv("ENV_VAR1")).thenReturn("1234");
Exception:
org.mockito.exceptions.base.MockitoException:
'afterPropertiesSet' is a *void method* and it *cannot* be stubbed with a *return value*!
Voids are usually stubbed with Throwables:
doThrow(exception).when(mock).someVoidMethod();
***
Use the #RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
Use the #PrepareForTest({ClassThatCallsTheSystemClass.class}) annotation at the class-level of the test case.
Example with using EasyMock
public class SystemClassUser {
public String performEncode() throws UnsupportedEncodingException {
return URLEncoder.encode("string", "enc");
}
}
And test
#RunWith(PowerMockRunner.class)
#PrepareForTest( { SystemClassUser.class })
public class SystemClassUserTest {
#Test
public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
mockStatic(URLEncoder.class);
expect(URLEncoder.encode("string", "enc")).andReturn("something");
replayAll();
assertEquals("something", new SystemClassUser().performEncode());
verifyAll();
}
}
From:
https://github.com/powermock/powermock/wiki/MockSystem
So, you should add a class that uses the System.getenv, not the System class to #PrepareForTest.
This post explains why it should be done in such way.
Also, I'd like to recommend to use the System Rules library for your case. It has a good way to stub environment variables. PowerMock modifies a class byte code, so it makes test slowly. And even if it not modify a class it at least read class from disk.

Invalid signature for SetUp or TearDown method - What am I doing wrong?

I am trying to do some dependency injection for my tests using nUnit. I'm new to TDD and nUnit so it's possible I am missing something simple. So basically I've created a SetUp method for my interfaces. I originally was using a constructor but I read it's bad to do this when doing TDD so I now using a method.
When I run my test I construct an object and assign it to the interface and then I call a method using that interface. I want to test if it can parse a string decimal.
When I run my test it says test failed and the message is:Invalid signature for SetUp or TearDown method
See below for the actual code:
public class DonorTests
{
private IDonor _Donor;
private IValidateInput _ValidInput;
//DonorTests(IDonor donor, IValidateInput validInput)
//{
// _Donor = donor;
// _ValidInput = validInput;
//}
[SetUp]
void Setup(IDonor donor, IValidateInput validInput)
{
_Donor = donor;
_ValidInput = validInput;
}
[Test]
public void HandleStringNotDecimal()
{
_ValidInput = new ValidateInput();
Assert.IsTrue(_ValidInput.IsDecimal("3445.3450"));
}
}
My class that uses this interface
public class ValidateInput : IValidateInput
{
public decimal RoundTwoDecimalPlaces(decimal amount)
{
return Math.Round(amount);
}
public bool IsDecimal(string amount)
{
decimal ParsedDecimal;
return Decimal.TryParse(amount, out ParsedDecimal);
}
public decimal ConvertToString(string value)
{
decimal ParsedDecimal;
Decimal.TryParse(value, out ParsedDecimal);
return ParsedDecimal;
}
}
You're injecting dependencies using constructor injection previously, right? I think you will not be able to perform dependency injection using method decorated with SetUpAttribute because such method has to be parameterless. Also Setup method has to be public, see this SO thread.
How are we typically dealing with similar situations in our company is:
[TestFixture]
public class DonorTests
{
private IDonor _Donor;
private IValidateInput _ValidInput;
[SetUp]
public void Setup()
{
_Donor = new Donor();
_ValidInput = new ValidateInput();
}
[Test]
public void HandleStringNotDecimal()
{
Assert.IsTrue(_ValidInput.IsDecimal("3445.3450"));
}
}
Or if construction of ValidInput and Donor is cheap then we simply create new instance for each test, having special method for that purpose so when we decide to test another implementation of IValidateInput then it is enough to change it in one place only:
[TestFixture]
public class DonorTests
{
[Test]
public void HandleStringNotDecimal()
{
var validInput = CreateValidateInput();
Assert.IsTrue(validInput .IsDecimal("3445.3450"));
}
private static IValidateInput CreateValidateInput()
{
return new ValidateInput();
}
}
Besides the cause mentioned in the accepted answer, I have met the same error when leaving method as non-public (private or protected).
NUnit most probably relies on reflection and does not deal with non-public methods, so special methods (i.e. decorated with NUnit specific attributes) must be public.

Unable to get default constructor for Integration class ninject

I'm new on using ninject and Dependency Injection, and have a problem using it.
I try to using Ninject on my class libray, and building an integration tests.
now, I see in many example that, for using ninject is just specified the DI Module like this:
Public Class DIModule : NinjectModule
public override void Load()
{
Bind<IUSAServices>().To<USAServices>();
}
And then on my test class, I try to call my dependency is like this:
[TestClass]
public class USAIntegrationTests
{
private readonly IUSAServices _usaService;
public USAIntegrationTests(IUSAServices usaServices)
{
_usaService = usaServices;
}
[TestMethod]
public void ValidateUserTests()
{
Assert.IsTrue(_usaService.ValidateUser("username1", "password1"));
}
}
And Getting this error:
Unable to get default constructor for class USATests.IntegrationTests.USAIntegrationTests.
However I read the documentation and tried like this:
[TestClass]
public class USAIntegrationTests
{
private readonly IUSAServices _usaService;
public USAIntegrationTests()
{
using (IKernel kernel = new StandardKernel(new DIModule()))
{
_usaService = kernel.Get<IUSAServices>();
}
}
[TestMethod]
public void ValidateUserTests()
{
Assert.IsTrue(_usaService.ValidateUser("mantab", "banget"));
}
}
The test is works properly.
My question is, why I getting that error? is that some way to get around it?
Thanks in advance.
Unit test frameworks require your test classes to have a default constructor. You usually can't integrate DI containers with them. Instead of using constructor injection, you will have to call the container directly from your code, although for unit tests you should typically not have a container at all (for integration tests however, this is okay).
You can add a paramterless constructor for the class. It worked for me.

Resources