Mockery - creating a mock in the constructor - unit-testing

Is there a way to create a mock in the test class constructor/class setUp function such that the mock is available to all test methods?
I have tried creating in the constructor like:
public class testMocks extends PHPUnit_Framework_TestCase {
protected $mock;
public function __construct()
{
$this->mock = Mockery::mock('myMockedClass');
}
...
But this doesn't work. If the first test passes, then all tests that assert on the mock pass even if they should fail (i.e running a shouldReceive that should fail). Any ideas?

You have to use setUp function, like this:
public function setUp()
{
$this->mock = Mockery::mock('myMockedClass');
}

You shouldn't overwrite the constructor of PHPUnit_Framework_TestCase, see my answer on #15051271 and also #17504870
You also need to call Mockery::close() on tearDown method. The close method cleans up the mockery container for your next test and runs the expectations you have setup.
public function tearDown()
{
Mockery::close();
}

Related

Mockito cannot mock java.lang.reflect.Method

please help.
I have a class to test against with junit test.
Class
#Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
...
final Object toReturn = method.invoke(this.impl, objects);
...
}
Test class I have
#Test
public void test() throws Throwable {
try {
APIController apiController = new APIController(paramMock1, new Gson());
Method method = apiController.getClass().getMethod("ping");
methodMock = Mockito.mock(method.getClass()); **---> Fail**
Mockito.doNothing().when(methodMock).invoke(Mockito.anyObject(), Mockito.any());
proxy.invoke(new Object(), method, new Object[]{});
} catch (Exception ex) {
Assert.assertTrue(ex instanceof NullPointerException);
}
}
The error message is
Cannot mock/spy class java.lang.reflect.Method
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types`
I did some research and added
#RunWith(PowerMockRunner.class)
on top of test class, but error still comes.
How can I test with a mocked of this Method? Thank you.
PowerMock and Mockito are different mocking frameworks, so just adding the #RunWith(PowerMockRunner.class) annotation would not solve your problem. Powermock could be useful (I'm not very familiar with it, so not sure here), but you would need to rewrite the test to use it instead of mockito.
But from what I see you most likely don't need to mock the Method class — for your task it would be sufficient to just mock the object on which you want to mock the method. Something like this:
APIController apiController = mock(APIController.class);
doNothing().when(apiController).ping(...);
// pass the mocked apiController to your proxy;
// test that proxy.invoke calls the ping method

Fake internal calls of a SUT with FakeItEasy

I have a small C# class that handles printing.
I want to create (n)unit tests for this class, using
fakeItEasy. How can I fake the internal calls of this
class without faking the whole SUT ?
For example:
public class MyPrintHandler: IMyPrintHandler
{
public MyPrintHandler(ILogger<MyPrintHandler> logger)
{
}
// function I want to (unit test
public async Task<bool> PrintAsync(string ipaddress)
{
try
{
if (!string.IsNullOrWhiteSpace(ipaddress) )
{
return await StartPrint(ipaddress); // This cannot be called in a unit test, because it really start printing on a printer.
}
}
catch (Exception e)
{
}
return false;
}
private async Task<bool> StartPrint(string ipaddress)
{
// prints on the printer
}
[TestFixture]
public class MyPrintHandlerTests
{
[Test]
public void Succes_PrintAsync()
{
using (var fake = new AutoFake())
{
// Arrange - configure the fake
var sut = fake.Resolve<MyPrintHandler>();
// Act
await sut.PrintAsync("0.0.0.0"); // I want to prevent StartPrint() from being called..
}
}
}
How can I achieve this, or is this not possible at all?
Thanks in advance!
I would typically say that faking the SUT is an anti-pattern, to be avoided whenever possible, as it causes confusion. If you can refactor to introduce a collaborator that handles the StartPrinting method, I would strongly consider doing so. If this is not possible, you can try this, however
any method that you want to fake must be virtual or abstract, otherwise FakeItEasy cannot intercept it
any method that you want to fake must be public (or internal, if you can grant dynamic proxy access to production code's internals)
you would then fake the SUT, specifying that it should call the original (base) methods, and finally
explicitly override the behaviour for the method that you want to intercept

Wanted but not invoked: Mockito and Retrofit

I'm trying to unit test a call to my api using Mockito.
I took a look at all the issues already mentioned here on S.O together with the solutions, but so far, none of them have been conclusive.
MyService is an interface which holds several resources. Here's a sample:
public interface MyService {
#GET("/myresource")
Call<MyResponse> getDataFromServer();
}
Inside my Application class, I have a static class which returns an instance of MyService
public static MyService getApiService() {
return mApiService;
}
So, from there on inside one of my classes, I make the call to the web service:
Call<MyResponse> call = getApiService.getDataFromServer();
call.enqueue(myCallback)
The rest follows with the callback method being called....
Here's my test class:
#RunWith(AndroidJUnit4.class)
public class SampleTest {
#Mock
private MyService mService;
#Captor
private ArgumentCaptor<Callback<MyResponse>> callbackArgumentCaptor;
#Mock
private Call<MyResponse> mockCall;
// Rule to trigger the creation of #Mock annotated objects.
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Test
public void testDoAction() throws NullInsteadOfMockException {
when(mService.doSomeAction()).thenReturn(mockCall);
mService.doSomeAction();
verify(mockCall).enqueue(callbackArgumentCaptor.capture());
}
}
Here's the error I have once I run the test:
Wanted but not invoked:
mockCall.enqueue(
<Capturing argument>
);
Actually, there were zero interactions with this mock.
I have the same error even if use MockitoJunitRunner (in place of AndroidJunitRunner) and initialize my mock objects inside a setup method I define like this:
#Before
public void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
}
Mockito version : 2.7.19
I want to be able to test the API response, so I mocked the API service, defined a captor for the retrofit Callback
It's a bit strange what you're trying to do here. You're testing a class, but you mock it. You should test the real class - MyService. I assume that your service looks a bit like:
public class MyService {
private final Call<MyResponse> call;
public MyService(Call<MyResponse> call) {
this.call = call;
}
public void doSomeAction() {
call.enqueue(...);
}
}
Ideally you should have something like:
#RunWith(AndroidJUnit4.class)
public class SampleTest {
private MyService mService;
#Captor
private ArgumentCaptor<Callback<MyResponse>> callbackArgumentCaptor;
#Mock
private Call<MyResponse> mockCall;
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Before
public void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
mService = new MyService(mockCall);
}
#Test
public void testDoAction() throws NullInsteadOfMockException {
mService.doSomeAction();
verify(mockCall).enqueue(callbackArgumentCaptor.capture());
}
}
So the idea is to mock all the dependencies of the class you're unit testing and pass them to the class somehow. Here I'm injecting them in the constructor. I don't know if this is the case for you, but a setter or a field works too.
Then the test simply calls the real method in the service class and if this method is suppose to enqueue the call, then the verify should pass.
The reason it doesn't work in your case is because you're mocking the service so when you call mService.doSomeAction() this doesn't call your implementation, which I suppose should call enqueue. This is why the verify fails. In other words, it's true that enqueue is never called on the call object.

Spring boot mocking static methods with PowerMock in Integration test

I'm writing integration test on a RestController in SpringBoot.
Normally I would run with SpringRunner.class, but when it comes to Mock a static method I need to use PowerMock.
The strange fact is that when I run the single tests, they individually pass (but returns error messages), when I try to run the entire test class, no test passes and it returns the same error message.
#RunWith(PowerMockRunner.class)
#PrepareForTest({JwtUtils.class})
//#PowerMockRunnerDelegate(SpringRunner.class) THIS DOESN'T WORK!!!
#SpringBootTest(classes = SpringBootJwtApplication.class)
public class RestAccessIntegrationTest {
#Autowired #InjectMocks
RestController restController;
#Mock
HttpServletRequest request;
#Test
public void operationsPerAccountWhenSuccessfulTest(){
mockStatic(JwtUtils.class);
when(JwtUtils.myMethod(request)).thenReturn("blabla");
String expected = ... ;
String actual = restController.getOperations();
assertEquals(actual, expected);
}
}
If I run the test or the entire class I get an error of this type:
Exception in thread "main" java.lang.NoSuchMethodError: org.powermock.core.MockRepository.addAfterMethodRunner(Ljava/lang/Runnable;)at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:50)
If I uncomment #PowerMockRunnerDelegate(SpringRunner.class) there it comes this other error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/powermock/core/testlisteners/GlobalNotificationBuildSupport$Callback
at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:139)
In the when method, try using any(HttpServletRequest.class) instead of the request mock object. Also use MockHttpServletRequest instead of mocking HttpServletRequest. This should work,
#RunWith(PowerMockRunner.class)
#PrepareForTest(JwtUtils.class)
#PowerMockIgnore( {"javax.management.*"})
public class RestAccessIntegrationTest {
#InjectMocks
private RestController restController;
private MockHttpServletRequest request;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
request = new MockHttpServletRequest();
RequestContextHolder.setRequestAttributes(
new ServletRequestAttributes(request));
}
#Test
public void operationsPerAccountWhenSuccessfulTest() {
mockStatic(JwtUtils.class);
when(JwtUtils.myMethod(any(HttpServletRequest.class)))
.thenReturn("blabla");
String expected = ... ;
// does your getOperations take HttpServletRequest
// as parameter, then controller.getOperations(request);
String actual = restController.getOperations();
assertEquals(actual, expected);
}
}
It was due to incompatibility in library version of PowerMock and Mockito. I suggest to check the compatibility version table provided by PowerMock team or to switch to JMockit to mock static and private methods.

Use Mockito to unit test a function which calls async function

I have a method which calls async function:
public class MyService {
...
public void uploadData() {
MyPool.getInstance().getThreadPool().execute(new Runnable() {
#Override
public void run() {
boolean suc = upload();
}
});
}
}
I want to unit test this function with Mockito, I tried:
MyPool mockMyPool = Mockito.mock(MyPool.class);
ThreadPool mockThreadPool = Mockito.mock(ThreadPool.class);
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
when(mockMyPool.getThreadPool()).thenReturn(mockThreadPool);
MyService service = new MyService();
// run the method under test
service.uploadData();
// set the runnableCaptor to hold your callback
verify(mockThreadPool).execute(runnableCaptor.capture());
But I got error:
org.mockito.exceptions.verification.WantedButNotInvoked:
Wanted but not invoked:
threadPool.execute(
<Capturing argument>
);
Why I got this error, how to unit test uploadData() function with Mockito?
OK, I figured out a way by myself, since MyPool is an singleton. I added one public function setInstance(mockedInstance) to pass the mocked instance to MyPool. Then, it works. I know it is a bit "dirty", but if you have better solution, please let me know. Thanks!
Aside from the DI approach you found of keeping a MyPool or ThreadPool field, you can also refactor a little bit to allow for dependency injection in your method:
public class MyService {
...
public void uploadData() {
uploadData(MyPool.getInstance().getThreadPool());
}
/** Receives an Executor for execution. Package-private for testing. */
void uploadData(Executor executor) {
executor.execute(new Runnable() {
#Override public void run() {
boolean suc = upload();
}
});
}
}
This might be even cleaner, because it reduces your ThreadPool to the level of abstraction you need (Executor), which means you're only mocking a one-method interface rather than your ThreadPool (which I assume is related to ThreadPoolService; otherwise, you can just accept a ThreadPool, too). Officially your uploadData() would be untested, but you could easily and thoroughly test uploadData(Executor) or uploadData(ThreadPool), which are the moving parts most likely to break.
The package-private trick does rely on your code and tests to be in the same package, though they could be in different source folders; alternatively, you could just make the ThreadPool-receiving call a part of your public API, which would allow for more flexibility later.