Is possible to finish unit testing when a method is called? - unit-testing

Here is my test method where It should be success if showLoading() and loadDataSuccess(response) was called:
#RunWith(PowerMockRunner.class)
public class PresenterTest {
#Mock
private ProfileContract.View view;
#Mock
private ProfileContract.Handler handler;
#Test
public void onLoadDataClicked() {
presenter.loadData();
verify(mView, times(1)).showLoading();
verify(mHandler, times(1)).loadDataSuccess();
}
}
UPDATE 1
Here is my presenter:
class ProfilePresenter(private val mView: ProfileContract.View) : ProfileContract.Handler {
override fun loadData() {
mView.showLoading()
mUserService.user()
.compose(RxUtil.mapper())
.subscribe({ response ->
loadDataSuccess()
}, { error ->
//stuff
})
}
}
Thanks!

If you use return statment, your test finish with success status.

I think there is a basic problem with your test setup:
You do not use verify to check if one function calles another function within the same class. Verify is used to verify that the tested class calls function on other (mocked) classes. If I am not mistaken, your setup should actually give you an error message saying that you can not use verify on instantiated classes.
What you should do -if you want to check if onCompleteClicked() produces the correct results- is to check if the data that gets changed inside the onStuffComplete() function is set correctly. You can use an assert for that.
As an example, lets say onStuffCompleted() sets completeCounter to 1
#Test
public void onCompleteClicked() {
presenter.onStuffCompleteClicked();
assertEquals(completCounter , 1);
}
And to answer your original question: verify (and assert) will pass if the requirements were met (and by this the whole test will pass) and fail if not. You do not need to add any additional stuff (but once again: verify will only work with mocked classes).

Related

Java - Unit testing a void method using Matchers

I am trying to test a void method such as following:
#Override
public void onApplicationEvent(ApplicationEvent myEvent) {
if (myEvent instanceof ApplicationEnvironmentPreparedEvent) {
ConfigurableEnvironment myEnv= ((ApplicationEnvironmentPreparedEvent) myEvent).getEnvironment();
setSystemVariables(myEnv);
}
}
I am using Matchers and here is the unit test (which obviously is not testing anything)
#Test
public void testOnApplicationEvent() {
loggingListener.onApplicationEvent(any(ApplicationEnvironmentPreparedEvent.class));
}
Two issues:
1. The error I get from the build is "Invalid use of Matchers" and test doesn't pass in my Jenkins build (but passes in idea IDE)
2. How to test these methods to keep the test coverage percentage up to a desired level
1 - This issue because any is used incorrectly. Refer the Mockito guide for details. Below my example does not use any and the problem will be gone.
2 - To cover 2 branches of if I would recommend below test cases.
#Test
public void onApplicationEventShouldSetEnvironmentWhenApplicationEnvironmentPreparedEvent() {
ConfigurableEnvironment actualEnvironment = null;
// Given a listener with overridden setSystemVariables() to store passed env.
LoggingListener loggingListener = new LoggingListener() {
#Override
void setSystemVariables(ConfigurableEnvironment var){
actualEnvironment = var;
}
};
// Given some dummy environment which is delivered by an event.
ConfigurableEnvironment expectedEnvironment = new ConfigurableEnvironment();
// Given a mocked event with above dummy environment.
ApplicationEvent mockedEvent = Mockito(ApplicationEnvironmentPreparedEvent.class);
Mockito.when(mockedEvent.getEnvironment()).returns(expectedEnvironment);
// When call a method under test
loggingListener.onApplicationEvent(mockedEvent);
// Then make sure the given environment was passed and set correctly
assertSame(expectedEnvironment, actualEnvironment);
}
#Test
public void onApplicationEventShouldSkipNotApplicationEnvironmentPreparedEvent() {
// Given a listener with overridden setSystemVariables() to fail the test if called.
LoggingListener loggingListener = new LoggingListener() {
#Override
void setSystemVariables(ConfigurableEnvironment var){
fail("This method should not be called");
}
};
// Given a mocked other (not ApplicationEnvironmentPreparedEvent) event.
ApplicationEvent mockedEvent = Mockito(UnknownEvent.class);
// When call a method under test
loggingListener.onApplicationEvent(mockedEvent);
// Then make sure an environment was not asked at all.
Mockito.verify(mockedEvent.getEnvironment(), never);
}
Note, this is not compilable code, because I don't know your full production code, so treat this as an idea to apply it on your real code with corresponding modifications.

How to unit test that object was passed with correct state?

Lets say there is such function:
function a()
{
$entity = $this->getEntity();
$entity->setSomePrivateVar();
$service = $this->getService();
$service->doSomething($entity);
}
I want to test that
$service->doSomething($entity);
is called with correct $entity.
The $entity calls setSomePrivateVar()
In real application code I have done something like this:
Get mock of entity and test that setSomePrivateVar is called.
Get mock of $service and test that doSomething() is called with parameter $entity.
Looks ok.
But the problem is - if I refactor code and first call doSomething() on service and then setSomePrivateVar() on $entity, test still passes.
But the function is now wrong, because doSomething is depending on $entity private field which is set by setSomePrivateVar().
For example I would refactor to this:
function a()
{
$entity = $this->getEntity();
$service = $this->getService();
$service->doSomething($entity);
// this line moved
$entity->setSomePrivateVar();
}
So it looks like PhpUnit is not checking $entity private fields. If it was for example array, then with() function would see that array passed is not same as expected.
So how do I test that doSomething() gets $entity in correct state (that setSomePrivateVar() was called on entity before passing it to doSomething() )?
Maybe it has something to do that $entity is mocked.
Update with real world example
public function setNotifyUsers(AnnualConsolidation $consolidation, $status)
{
$consolidation->setNotifyUsers($status); // if move this method after the flush(), tesst does not fail
$this->entityManager->persist($consolidation);
$this->entityManager->flush();
}
public function testNotifyUsers()
{
$consolidation = $this->getMockBuilder(AnnualConsolidation::class)
->setMethods(['setNotifyUsers'])
->getMock();
$consolidation
->expects($this->once())
->method('setNotifyUsers')
;
$this->entityManager
->expects($this->at(0))
->method('persist')
->with($consolidation)
;
$this->entityManager
->expects($this->at(1))
->method('flush')
;
/** #var AnnualConsolidation $consolidation */
$this->consolidationsService->setNotifyUsers($consolidation, true);
}
We were discussing if testing the setNotifyUsers method this way is even good. I was trying to test without hitting the database. One guy thinks that this might be needed to test with hitting database, because if refactoring method without changing logic, test might be needed to refactor. On the other hand - this method is not likely to be refactored that much.
But maybe also there is a way to just test that flush() is called after persist() without telling indexes, because in other examples, the indexes then might be needed to update after adding some call before persist and so might be too much work to keep tests working.
But for this topic - first I want to know how to make test fail - if I move setNotifyUsers after the flush(). Test is not failing. While if we would test with hitting database - we would see that $consolidation status is not updated.
One guy told to check, assert what is passed to the persist method. I did not try yet, but I am not sure if on mocked $consolidation this will be possible. Does mocked $consolidation has some state as real $consolidation would have?
As you say in your question
One guy told to check, assert what is passed to the persist method.
That would be the way to go but your code makes that rather hard and i think you should refactor a bit to make the code testable.
First your method is called "setNotifyUsers" but it does actually do 2 actions it calls the setNotifyUsers on the consolidation object and it saves/persists this data.
In my opinion those are 2 different actions that should belong in 2 different methods. It could help your test if you wrote it like :
public function setNotifyUsers(AnnualConsolidation $consolidation, $status) {
$consolidation->setNotifyUsers($status);
}
public function persistConsolidation(AnnualConsolidation $consolidation) {
$this->entityManager->persist($consolidation);
$this->entityManager->flush();
}
You could test the setNotifyUser and persistConsolidation sepperately and write a functional test for the part that calls these functions (the methods that use the consolidationsService)
then you can use the at() functionality to see if those functions are called in the correct order.
But:
Second you give both the state as the consolidation to this function with as only reason to add those together. i don't think something like that belongs in the service but rather in the method
calling that service.
Moving that functionality will again give you trouble as you cannot test the order in which they are called.
But you don't need to use the mockBuilder to make a test double.
Instead of using $this->getMockBuilder you can also create a FakeConsolidation that will actually hold the data for you
Then you will also need a mock for the AnnualConsolidation because you want to be able to check if the value was correctly set.
class FakeConsolidation extends AnnualConsolidation {
protected $id;
proteced $status;
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
}
public function setNotifyUsers($status) {
$this->status = $status;
}
public function shouldNotifyUsers() {
$this->status
}
}
Now because you will give an object to the persist that has a state we can check that state in the "with" part.
Of course, I do not know exactly how your code is structured so I made some assumptions just adapt where needed and use the interfaces that you have.
Like this you could even test the code as you presented it in this question:
class SomethingTest extends PHPUnit_Framework_TestCase {
private $consolidationsService;
private $entityManager;
/**
* {#inheritdoc}
*/
public function setUp() {
$this->entityManager = $this->getMockBuilder(EntityManager::class)->getMock();
$this->consolidationsService = new ConsolidationsService($this->entityManager);
}
public function testNotifyUsers() {
$consolidation = new FakeConsolidation();
$consolidation->setId(1);
$this->entityManager
->expects($this->at(0))
->method('persist')
->with($this->callback(
function($savedConsolidation) {
return $savedConsolidation->shouldNotifyUsers() === true;
}
));
$this->entityManager
->expects($this->at(1))
->method('flush');
/** #var AnnualConsolidation $consolidation */
$this->consolidationsService->setNotifyUsers($consolidation, TRUE);
}
}
Now when you move the setNotifyUsers below the persist
with($this->callback(
function($savedConsolidation) {
return $savedConsolidation->shouldNotifyUsers() === true;
}
));
Your test will fail because the status is not set yet.

Method with argument of AbstractController phpunit. Any hints

I need to test method which looks like this, but my question is: How i should enter this method especially when i can not "mock" AbstractController, and without variable of AbstractController it would not work
public function add(\Queue\Controller\AbstractQueueController $task)
{
//Logic of method
}
You don't need to mock it. You already set it as a parameter, so this test is not about testing AbstractQueueController.
So, for example, if your function looks like this :
public function add(\Queue\Controller\AbstractQueueController $task)
{
$task->doSomething();
}
Then, in the test,AbstractQueueController should receive a call to doSomething method(), and then assert the result of that.
well i did something like that i made extended class
class addtest extends Queue\Controller\AbstractQueueController
{
public function task()
{
}
}
and then in my QueeuServiceTest extended by PHPUnit_framework_TestCase
i made testmethod
public function testadd()
{
$this->queueService->add(new addtest);
}
it covers code but i do not know it is good practice

Testing private methods in java using Powermockito

I am using PowerMockito and jUnit to write unit test cases.
public class Foo {
private String resolveApplicationId() {
return "testApplication";
}
}
Here is my test case
#RunWith(PowerMockRunner.class)
#PrepareForTest(Foo.class)
public class test{
#Before
public void prepareTest() {
foo = PowerMockito.spy(new Foo());
}
#Test
public void checkApplicationIdIsResolved() throws Exception {
PowerMockito.doNothing().when(foo, "myPrivateMethod");
PowerMockito.verifyPrivate(foo).invoke("myPrivateMethod");
//Assert Here the returned value
}
}
Please tell me
1. how can I assert the value returned by the method when it is called
2. how can I call the private method
3. if not then what actually I verify when I write test case for private methods.
Thanks.
Testing private method does not differ from testing public method. If there is no external dependencies you even don't need to create and use any mocks. The only problem is with invocation of the private method from test. This is described here or you may use spring utils.
So you don't need to mock the method you are testing. You only require to mock other objects which are not tested in this particular test. So you test would look like
#Test
public void checkApplicationIdIsResolved() throws Exception {
// makeResolveIdAccessible();
// if needed setup mocks for objects used in resolveApplicationId
assertEquals(expectedApplicationId, foo.resolveApplicationId())
}

How to use Rhino Mock to mock a local function calling?

Here is my situation:
I want to test on the "HasSomething()" function, which is in the following class:
public class Something
{
private object _thing;
public virtual bool HasSomething()
{
if (HasSomething(_thing))
return true;
return false;
}
public virtual bool HasSomething(object thing)
{
....some algo here to check on the object...
return true;
}
}
So, i write my test to be like this:
public void HasSomethingTest1()
{
MockRepository mocks = new MockRepository();
Something target = mocks.DynamicMock(typeof(Something)) as Something;
Expect.Call(target.HasSomething(new Object())).IgnoreArguments().Return(true);
bool expected = true;
bool actual;
actual = target.HasSomething();
Assert.AreEqual(expected, actual);
}
Is my test written correctly?
Please help me as i can't even get the result as expected. the "HasSomething(object)" just can't be mock in that way. it did not return me 'true' as being set in expectation.
Thanks.
In response to OP's 'answer': Your main problem is that RhinoMocks does not mock members of classes - instead it creates mock classes and we can then set expectations and canned responses for its members (i.e. Properties and Functions). If you attempt to test a member function of a mock/stub class, you run the risk of testing the mocking framework rather than your implementation.
For the particular scenario of the logical path being dependent on the return value of a local (usually private) function, you really need an external dependency (another object) which would affect the return value that you require from that local function. For your code snippet above, I would write the test as follows:
[Test]
public void TestHasSomething()
{
// here I am assuming that _thing is being injected in via the constructor
// you could also do it via a property setter or a function
var sut = new Something(new object());
Assert.IsTrue(sut.HasSomething);
}
i.e. no mocking required.
This is one point of misunderstanding that I often had in the past with regards to mocking; we mock the behaviour of a dependency of the system under test (SUT). Something like: the SUT calls several methods of the dependency and the mocking process provides canned responses (rather than going to the database, etc) to guide the way the logic flows.
A simple example would be as follows (note that I have used RhinoMocks AAA syntax for this test. As an aside, I notice that the syntax that you are using in your code sample is using the Record-Replay paradigm, except that it isn't using Record and Replay! That would probably cause problems as well):
public class SUT
{
Dependency _depend
public SUT (Dependency depend)
{
_depend = depend;
}
...
public int MethodUnderTest()
{
if (_depend.IsReady)
return 1;
else
return -1;
}
}
...
[Test]
public void TestSUT_MethodUnderTest()
{
var dependency = MockRepository.GenerateMock<Dependency>();
dependency.Stub(d => d.IsReady).Return(true);
var sut = new SUT(dependency);
Assert.AreEqual(1, sut.MethodUnderTest());
}
And so the problem that you have is that you are attempting to test the behaviour of a mocked object. Which means that you aren't actually testing your class at all!
In a case like this, your test double should be a derived version of class Something. Then you override the method HasSomething(object) and ensure that HasSomething() calls your one.
If I understand correctly, you are actually interested in testing the method HasDynamicFlow (not depicted in your example above) without concerning yourself with the algorithm for HasSomething.
Preet is right in that you could simply subclass Something and override the behavior of HasSomething to short-circuit the algorithm, but that would require creating some additional test-dummy code which Rhino is efficient at eliminating.
Consider using a Partial Mock Stub instead of a Dynamic Mock. A stub is less strict and is ideal for working with Properties. Methods however require some extra effort.
[Test]
public void CanStubMethod()
{
Foo foo = MockRepository.GenerateStub<Foo>();
foo.Expect(f => f.HasDynamicFlow()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething()).CallOriginalMethod(OriginalCallOptions.NoExpectation);
foo.Expect(f => f.HasSomething(null)).IgnoreArguments().Return(true);
Assert.IsTrue(foo.HasDynamicFlow());
}
EDIT: added code example and switched Partial Mock to Stub