JUnit 5 Mockito Stubbing Referenced Method and Verifying it was Called - mockito

I'm working with JUnit5 and their ParameterizedTest feature. How do I work with method references as part of the data source?
Example:
public enum Status {
APPROVE, DECLINE
}
#Mock
public MockService mockService;
// Normal Test
#Test
void testApprove() {
Mockito.doReturn(null)
.when(mockService)
.approveCall();
Mockito.verify(mockService).approveCall();
}
// Parameterized Test
Map<Status, Supplier<?>> mockMap = Map.ofEntries( // Java 9 method
Map.entry(APPROVE, mockService::approveCall),
Map.entry(DECLINE, mockService::declineCall)
);
#ParameterizedTest
#EnumSource(Status.class)
void test(Status status) {
Supplier<?> supplier = mockMap.get(status);
??
}
I want my second test to do the same thing as my first test, but also covering the DECLINE value. How do I parameterize the mock method reference?

I worked around it with a few functional/lambda tricks.
public class MyTest {
public enum Status {
APPROVE, DECLINE
}
#Mock
public MockService mockService;
// Parameterized Test
Map<Status, MockitoVerifier> mockMap = Map.ofEntries( // Java 9 method
Map.entry(Status.APPROVE, () -> Mockito.verify(mockService).approveCall()),
Map.entry(Status.DECLINE, () -> Mockito.verify(mockService).declineCall())
);
#ParameterizedTest
#EnumSource(Status.class)
void test(Status status) {
MockitoVerifier<?> verifier = mockMap.get(status);
verifier.verify();
}
#FunctionalInterface
interface MockitoVerifier<T> {
T verify();
}
}

Related

mockito, how to verify static member function

having a class which internally generates error msg and using static function of android,util.Log.i(String, String) to log the error (it could be some other static function to recored the failure).
class Util {
public static void handleIntent(Intent intent, String Tag, String failMsg) {
...
if (true) { // for test
String s = failMsg; //getError(failCode);
Log.i(Tag, s);
}
...
}
}
and the test is to verify the error message is logged (using mockito-inline 3.8.0):
#Test
public void test_log() {
try (MockedStatic<Log> logMock = Mockito.mockStatic(Log.class)) {
Intent intent = getIntent();
// test
Util.handleIntent(intent, "theTag", "+++TEST1");
// verify
Mockito.verify(logMock, times(1)).i(eq(theTag), eq("+++TEST1")); //<== does not compile
Log.i(eq("+++TEST1"), eq(dataStr));
}
}
how to mock the android.util.Log and verify its static android.util.Log.i(String, String) has been called with the string?
(powermock is not the option. it was using powermock and after update the mockito to 3.8.0 and powermock to 2.0.9, it starts to get a lot errors, and was suggested to replace the powermock with mockito-inline.)
You would add a "logMock.when" instruction before you test's instruction.
this works:
try (MockedStatic<Log> logMock = Mockito.mockStatic(Log.class)) {
// test
Util.handleIntent(intent, "theTag", "+++TEST1");
logMock.verify(() -> Log.i(eq("theTag"), eq("+++TEST1"), times(1));
}

How to mock a object construction that is created using reflection i.e newInstance() method

I have a piece of code below where Employee class creates object of AppraisalCalculator using reflection. I want to mock this AppraisalCalculator object using PowerMockito.
class AppraisalCalculator {
public int appraisal() {
return 300;
}
}
class Employee {
public int updateSalary() {
// line 1
AppraisalCalculator ac =
AppraisalCalculator.class.getConstructor().newInstance();
return ac.appraisal();
}
}
class TestRunner {
#Test
public void test() {
AppraisalCalulator acMock=PowerMockito.mock(AppraisalCalculator.class);
PowerMockito
.whenNew(AppraisalCalculator.class)
.withNoArguments()
.thenReturn(600);
Employee emp = new Employee();
int actualValue = emp.updateSalary();
int expectedValue=600;
Assert.equals(expectedValue,actualValue);
}
}
Here, even though I have mocked the Appraisal calculator object, it still calls the real appraisal() method from AppraisalCalculator. If the actual AppraisalCalculator at line 1 is created using new Operator instead of newInstance() then this mocking works.
Can anyone explain why this is not working if the actual object is created using reflection? What can I do to mock this Object in such scenario?
Let me first start by rephrasing your question will fully working code.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Employee.class)
public class TestRunner {
#Test
public void test() throws Exception {
AppraisalCalculator acMock = PowerMockito.mock(AppraisalCalculator.class);
PowerMockito
.whenNew(AppraisalCalculator.class)
.withNoArguments()
.thenReturn(acMock);
when(acMock.appraisal()).thenReturn(600);
Employee emp = new Employee();
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}
}
Then, the way PowerMock works is that the PowerMockRunner will look at each class that needs to be prepared (here Employee), then look for a call to the constructor we want to replace and do it. This is done at class loading. The real class bytecode calling the constructor is replaced by the one returning the mock.
The thing is that if you are using reflection, PowerMock can't know by reading the bytecode that this constructor will be called. It will only be known dynamically afterwards. So no mocking done.
If you really do need to create the class to be mocked by reflection, I would actually refactor the code a bit.
In Employee I would add something like
protected AppraisalCalculator getCalculator() {
try {
return AppraisalCalculator.class.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
while is a method dedicated to isolate the calculator construction.
The, just create a child class
#Test
public void testWithChildClass() {
// Note that you don't need PowerMock anymore
AppraisalCalculator acMock = Mockito.mock(AppraisalCalculator.class);
when(acMock.appraisal()).thenReturn(600);
Employee emp = new Employee() {
#Override
protected AppraisalCalculator getCalculator() {
return acMock;
}
};
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}
or a partial mock (spy)
#Test
public void test2() {
// No PowerMock either here
AppraisalCalculator acMock = Mockito.mock(AppraisalCalculator.class);
when(acMock.appraisal()).thenReturn(600);
Employee emp = spy(new Employee());
doReturn(acMock).when(emp).getCalculator();
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}

How to stub a private method of a class written in typescript using sinon

I am writing unit tests for a public method which is, in turn, calling a private method of the class written in typescript (Node JS).
Sample Code
class A {
constructor() {
}
public method1() {
if(this.method2()) {
// Do something
} else {
// Do something else
}
}
private method2() {
return true;
}
}
Now to test method1() I need to stub method2() which is a private method.
here what I am trying :
sinon.stub(A.prototype, "method2");
Typescript is throwing the error :
Argument of type '"method2"' is not assignable to parameter of type '"method1"'
Any help would be appreciated.
Thank You
The problem is that the definition for sinon uses the following definition for the stub function :
interface SinonStubStatic { <T>(obj: T, method: keyof T): SinonStub; }
This means that the second parameter must be the name of a member (a public one) of the T type. This is probably a good restriction generally, but in this case it is a bit too restrictive.
You can get around it by casting to any:
sinon.stub(A.prototype, <any>"method2");
Sometimes when the complexity of code and tests is more significant I prefer to "externalize" private methods. You can do that, that either with a (partial) class or a (partial) interface.
it('private methods test', async () => {
// original class
class A{
public method1():string{
if(this.method2()) {
// Do something
return "true";
} else {
// Do something else
return "false";
}
}
// with private method
private method2():boolean{
return true;
}
}
// interface that makes the private method public
interface IAExternalized{
method2():boolean;
}
// class that makes the private method public
class APrivate implements IAExternalized{
// with public method
method2():boolean{
return true;
};
}
// test before mocking
let test:A = new A();
let result:string = test.method1();
result.should.be.equal("true");
// let's mock the private method, but with typechecking available
let stubMethod2:sinon.SinonStub = sinon.stub(<IAExternalized><unknown>(A.prototype), "method2").returns(false);
result = test.method1();
result.should.not.be.equal("true");
result.should.be.equal("false");
// access private method of an object through public-interface
let testPrivate:IAExternalized = <IAExternalized><unknown>test;
let result2:boolean = testPrivate.method2();
result2.should.not.be.equal(true);
result2.should.be.equal(false);
});
NOTE: If you control the code you are testing, you do not need to double code, prone to mistakes, but you can make your class implement the interface. To convert standard (without private) interface into "externalized" you can extend it with public methods.
export interface IAExternalized extends IAPrivate {
method2():boolean
};

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.

Mockito verify state halfway through test

I have some code that put simply, sets an object to a state of PROCESSING, does some stuff, then sets it to SUCCESS. I want to verify that the PROCESSING save is done with the correct values.
The problem is when the verify() tests are performed, .equals() is called on the object as it is at the end of the test, rather than halfway through.
For example the code:
public void process(Thing thing) {
thing.setValue(17);
thing.setStatus(Status.PROCESSING);
dao.save(thing);
doSomeMajorProcessing(thing);
thing.setStatus(Status.SUCCESS);
dao.save(thing);
}
I want to test:
public void test() {
Thing actual = new Thing();
processor.process(actual);
Thing expected = new Thing();
expected.setValue(17);
expected.setStatus(Status.PROCESSING);
verify(dao).save(expected);
// ....
expected.setStatus(Status.SUCCESS);
verify(dao).save(expected);
}
On the first verify, actual.getStatus() is Status.SUCCESS, as Mockito just keeps a reference to the object and can only test it's value at the end.
I have considered that if a when(...) where involved then .equals() would be called at the correct time and the result would only happen if Thing was what I wanted it to be. However, in this case .save() returns nothing.
How can I verify that the object is put into the correct states?
Ok, I found a solution, but it's pretty horrible. Verify is no good to me because it runs too late, and stubbing is hard because the method returns a void.
But what I can do is stub and throw an exception if anything but the expected is called, while validating that something is called:
public void test() {
Thing actual = new Thing();
Thing expected = new Thing();
expected.setValue(17);
expected.setStatus(Status.PROCESSING);
doThrow(new RuntimeException("save called with wrong object"))
.when(dao).saveOne(not(expected));
processor.process(actual);
verify(dao).saveOne(any(Thing.class));
// ....
expected.setStatus(Status.SUCCESS);
verify(dao).saveTwo(expected);
}
private <T> T not(final T p) {
return argThat(new ArgumentMatcher<T>() {
#Override
public boolean matches(Object arg) {
return !arg.equals(p);
}
});
}
This infers that expected is called. Only drawback is that it'll be difficult to verify the method twice, but luckily in my case both DAO calls are to different methods, so I can verify them separately.
Why not just mock the Thing itself and verify that? eg:
public class ProcessorTest {
#Mock
private Dao mockDao;
#InjectMocks
private Processor processor;
#BeforeMethod
public void beforeMethod() {
initMocks(this);
}
public void test() {
Thing mockThing = Mockito.mock(Thing.class);
processor.process(thing);
verify(mockThing).setStatus(Status.PROCESSING);
verify(mockThing).setValue(17);
verify(mockDao).save(mockThing);
verify(mockThing).setStatus(Status.SUCCESS);
}
If you want to explicitly test the order in which these things happen, use an InOrder object:
public void inOrderTest() {
Thing mockThing = Mockito.mock(Thing.class);
InOrder inOrder = Mockito.inOrder(mockThing, mockDao);
processor.process(mockThing);
inorder.verify(mockThing).setStatus(Status.PROCESSING);
inorder.verify(mockThing).setValue(17);
inorder.verify(mockDao).save(mockThing);
inorder.verify(mockThing).setStatus(Status.SUCCESS);
inorder.verify(mockDao).save(mockThing);
}
Mockito has a problem verifying mutable objects. There is an open issue about this (http://code.google.com/p/mockito/issues/detail?id=126)
Maybe you should switch to EasyMock. They use a record/playback pattern and do the verification at the time of the call in contrary to Mockito, where the verification happens after the call.
This Mockito version of the test has the mentioned problem:
#Test
public void testMockito() {
Processor processor = new Processor();
Dao dao = Mockito.mock(Dao.class);
processor.setDao(dao);
Thing actual = new Thing();
actual.setValue(17);
processor.process(actual);
Thing expected1 = new Thing();
expected1.setValue(17);
expected1.setStatus(Status.PROCESSING);
verify(dao).save(expected1);
Thing expected2 = new Thing();
expected2.setValue(19);
expected2.setStatus(Status.SUCCESS);
verify(dao).save(expected2);
}
This EasyMock version works fine:
#Test
public void testEasymock() {
Processor processor = new Processor();
Dao dao = EasyMock.createStrictMock(Dao.class);
processor.setDao(dao);
Thing expected1 = new Thing();
expected1.setValue(17);
expected1.setStatus(Status.PROCESSING);
dao.save(expected1);
Thing expected2 = new Thing();
expected2.setValue(19);
expected2.setStatus(Status.SUCCESS);
dao.save(expected2);
EasyMock.replay(dao);
Thing actual = new Thing();
actual.setValue(17);
processor.process(actual);
EasyMock.verify(dao);
}
In my example doSomeMajorProcessing sets value to 19.
private void doSomeMajorProcessing(Thing thing) {
thing.setValue(19);
}
After reviewing https://code.google.com/archive/p/mockito/issues/126
I was able to get my version of this working (Java 15, Mockito 3.6.28):
// ========= CODE ==========
public void process(Thing thing) {
thing.setValue(17);
thing.setStatus(Status.PROCESSING);
dao.save(thing);
doSomeMajorProcessing(thing);
thing.setStatus(Status.SUCCESS);
dao.save(thing);
}
// ========= TEST ==========
// ++++++ NOTE - put this at class level
private final Dao dao = mock(Dao.class, withSettings().defaultAnswer(new ClonesArguments()));
public void test() {
Thing actual = new Thing();
processor.process(actual);
ArgumentCaptor<Thing> captor = ArgumentCaptor.for(Thing.class);
verify(dao, times(2)).save(captor.capture());
List<Things> savedCalls = captor.getAllValues();
assertEquals(Status.PROCESSING, savedCalls.get(0).getStatus());
assertEquals(Status.SUCCESS, savedCalls.get(1).getStatus());
}
Using argThat with a hamcrest Matcher should do the trick. The Matcher would match its passed thing if the thing has the PROCESSING status:
public class ProcessingMatcher extends BaseMatcher<Thing> {
#Override
public boolean matches(Object item) {
if (item instanceof Thing) {
return ((Thing) item).getStatus() == Status.PROCESSING;
}
return false;
}
#Override
public void describeTo(Description description) {
description.appendText(" has the PROCESSING status");
}
}
And then in your test, use the following code :
public class MyTest {
public void test() {
//...
mockDao.save(argThat(hasTheProcessingStatus()));
}
static ProcessingMatcher hasTheProcessingStatus() {
return new ProcessingMatcher();
}
}

Resources