How to verify to call or not to call a method - unit-testing

class MockView extends Mock implements ContactListViewContract {
#override
void onLoadContactsComplete(List<Contact> items) {
}
#override
void onLoadContactsError() {}
}
void main() {
test('ContactListPresenter test', () {
Injector.configure(Flavor.MOCK);
MockView view = new MockView();
ContactListPresenter presenter = new ContactListPresenter(view);
presenter.loadContacts();
verify(view.onLoadContactsComplete).called(1);
});
}
I want to make sure when presenter.loadContacts() is called from the code, then verify view.onLoadContactsComplete is called also but getting an error:
Used on a non-mockito object
Is there a possibility to do this with Mockito?
Update:
abstract class ContactListViewContract {
void onLoadContactsComplete(List<Contact> items);
void onLoadContactsError();
}
here the onLoadContactsComplete method is called
class ContactListPresenter {
ContactListViewContract _view;
ContactRepository _repository;
ContactListPresenter(this._view){
_repository = new Injector().contactRepository;
}
void loadContacts(){
assert(_view != null);
_repository.fetch()
.then((contacts) {
print(contacts);
_view.onLoadContactsComplete(contacts); // here the onLoadContactsComplete method is called
}).catchError((onError) {
print(onError);
_view.onLoadContactsError();
});
}
}
Mocked Repository. Fetch mocked data.
class MockContactRepository implements ContactRepository{
Future<List<Contact>> fetch(){
return new Future.value(kContacts);
}
}

when calling verify method you need call the actual method on the mock
Try
test('ContactListPresenter test', () async {
Injector.configure(Flavor.MOCK);
MockView view = new MockView();
ContactListPresenter presenter = new ContactListPresenter(view);
presenter.loadContacts();
await untilCalled(view.onLoadContactsComplete(typed(any)));
//completes when view.onLoadContactsComplete(any) is called
verify(view.onLoadContactsComplete(typed(any))).called(1);
});
If the method was not called once, the test will fail.

Mockito provides native support for both
To test that your method has been called at least once you can use
verify(<your-method-with-expected-params>) this will verify that your method has called (no matter how many times). To verify that it has been called for a specific number of times you can chain it with .called(<number-of-calls-expected>)
To test that your method hasn't been called you should use verifyNever(<your-method-with-expected-params>) this will validate that your method hasn't been invoked
Make sure that the method passed to both verify and verifyNever are the methods which have been Mocked by Mockito.

You can use never and verifyZeroInteractions
//interaction with mockOne
mockOne.add("one");
//ordinary interaction
verify(mockOne).add("one");
//we never interaction into the mock
verify(mockOne, never()).add("two");
//verify we don't use in the mock
verifyZeroInteractions(mockTwo, mockThree);
*mark verifyZeroInteractions as deprecated in mockito-kotlin, too
introduce an alias for verifyNoInteractions

Related

Mockery not executing mock method

I have class Name Validator and it has a method forVote.
This is my code.
public function test_should_set_default()
{
$this->mock = \Mockery::mock(Validator::class);
$this->mock->shouldReceive('forVote')
->andReturnTrue();
$this->app->instance(Validator::class,$this->mock);
$factory = new Factory();
$this->assertTrue($factory->setDefault());
}
So Factory calls Processor which calls Validator. Now I want mock validator to run. But it calls the real method.
What am I doing wrong?
https://laravel.com/docs/5.6/container#introduction
since the repository is injected, we are able to easily swap it out
with another implementation. We are also able to easily "mock", or
create a dummy implementation of the UserRepository when testing our
application.
My guess is you are perhaps currently instantiating your dependencies like so:
$processor = new Processor() and $validator = Validator::make(...);
So, in order to have your mocked class be used, you should use Dependency injection which just means your classes should inject your dependencies via the __construct method.
Your Factory class should be like:
class Factory {
$processor;
public function __construct(Processor $processor)
{
$this->processor = $processor;
}
public function setDefault()
{
$this->processor->callingValidator();
}
}
and your Processor to be like:
class Processor {
$validator;
/**
* The Validator will resolve to your mocked class.
*
*/
public function __construct(Validator $validator)
{
$this->validator = $validator;
}
public function callingValidator()
{
$this->validator->make();
}
}

Why "getSharedPreferences" return null in unit testing?

My classes is written in Kotlin and here is my SharedPreferenceHandler
class SharedPreferenceHandler(sharedPrefs: SharedPreferences) {
companion object {
var mInstance: SharedPreferenceHandler = SharedPreferenceHandler(getPrefs())
private fun getPrefs(): SharedPreferences {
return Application.mInstance.getSharedPreferences(
"myApp", Context.MODE_PRIVATE)
}
fun getInstance(): SharedPreferenceHandler {
return mInstance
}
}
private var sharedPreferences = sharedPrefs
var accessToken: String?
get() = sharedPreferences.getString(SharedPreference.ACCESS_TOKEN.name, null)
set(token) = sharedPreferences.edit().putString(SharedPreference.ACCESS_TOKEN.name, token).apply()
}
Here is method called in presenter:
override fun reload(vm: ViewModel) {
super.updateViewModel(vm) {
//some stuffs
}
}
Here is my test method:
#Test
public void reload() {
when(SharedPreferenceHandler.Companion.getMInstance().getAccessToken()).thenReturn("234234234234234");
presenter.reload(viewModel);
}
In handler from super.updateViewModel(vm) I call "SharedPreferenceHandler.mInstance.accessToken!!)"
That is what is thrown:
Caused by: java.lang.IllegalStateException:
Application.mInstanc…m", Context.MODE_PRIVATE) must not be null
at
com.zuum.zuumapp.preferences.SharedPreferenceHandler$Companion.getPrefs(SharedPreferenceHandler.kt:18)
at
com.zuum.zuumapp.preferences.SharedPreferenceHandler$Companion.access$getPrefs(SharedPreferenceHandler.kt:14)
at
com.zuum.zuumapp.preferences.SharedPreferenceHandler.(SharedPreferenceHandler.kt:15)
I wanna to get accessToken by calling " SharedPreferenceHandler.mInstance.accessToken!!" in my test class.
Is possible to get that in my test method?
You can't use Android SharedPreferences in unit test, but you can mock your method call by this:
Mockito.`when`(SharedPreferenceHandler.mInstance.accessToken).thenReturn("token")
And return what you need.
You should not test your code this way. You should create an interface for class you want to mock:
interface MySharedPreferences {
fun getAccessToken(): String
}
Let your SharedPreferencesHandler implements this interface. Then in your presenter (or other class you want to test) inject dependencies (f.e. by constructor or framework like Dagger/Kodein) into your object. Then there is possibility to easy mock this interface. I assume in #Before you create class you test - and then just pass as param your mocked SharedPreferencesHandler.
Testing things with static dependencies is possible, but is but tricky (and a lot of people consider static dependencies as anti-pattern). How to do it is described here: How to android unit test and mock a static method
Example:
class MyPresenter(val sp: MySharedPreferences) {
/* some code here */
fun validateToken() {
if (sp.getAccessToken() == "") throw new Exception()
}
}
Like you see sp is injected into this class as parameter. Normally you don't create views/presenters etc. directly in code but by DI framework (like Dagger or Kodein). Anyway, static dependencies are not easy testable. Injected interface-dependencies can be mocked, and you operating not on object, but on behaviors (so it's bigger level of abstraction). So, now in your test all you have to do is:
class MyTest() {
#Mock lateinit var sharedPreferencesMock: MySharedPreferences
lateinit var instance: MyPresenter
#Before
fun setUp() {
instance = MyPresenter(sharedPreferencesMock)
}
#Test
fun testSomething() {
`when`(sharedPreferencesMock.getAccessToken()).thenReturn("myAccessToken")
/* here is your test body */
}
}

How to use Moq to Prove that the Method under test Calls another Method

I am working on a unit test of an instance method. The method happens to be an ASP.NET MVC 4 controller action, but I don't think that really matters much. We just found a bug in this method, and I'd like to use TDD to fix the bug and make sure it doesn't come back.
The method under test calls a service which returns an object. It then calls an internal method passing a string property of this object. The bug is that under some circumstances, the service returns null, causing the method under test to throw a NullReferenceException.
The controller uses dependency injection, so I have been able to mock the service client to have it return a null object. The problem is that I want to change the method under test so that when the service returns null, the internal method should be called with a default string value.
The only way I could think to do this is to use a mock for the class under test. I want to be able to assert, or Verify that this internal method has been called with the correct default value. When I try this, I get a MockException stating that the invocation was not performed on the mock. Yet I was able to debug the code and see the internal method being called, with the correct parameters.
What's the right way to prove that the method under test calls another method passing a particular parameter value?
I think there's a code smell here. The first question I'll ask myself in such a situation is, is the "internal" method really internal/ private to the controller under test. Is it the controller's responsibility to do the "internal" task? Should the controller change when the internal method's implementation changes? May be not.
In that case, I would pull out a new targeted class, which has a public method which does the stuff which was until now internal to the controller.
With this refactoring in place, I would use the callback mechanism of MOQ and assert the argument value.
So eventually, you will end up mocking two dependancies:
1. The external service
2. The new targeted class which has the controller's internal implementation
Now your controller is completely isolated and can be unit tested independently. Also, the "internal" implementation becomes unit testable and should have its own set of unit tests too.
So your code and test would look something like this:
public class ControllerUnderTest
{
private IExternalService Service { get; set; }
private NewFocusedClass NewFocusedClass { get; set; }
const string DefaultValue = "DefaultValue";
public ControllerUnderTest(IExternalService service, NewFocusedClass newFocusedClass)
{
Service = service;
NewFocusedClass = newFocusedClass;
}
public void MethodUnderTest()
{
var returnedValue = Service.ExternalMethod();
string valueToBePassed;
if (returnedValue == null)
{
valueToBePassed = DefaultValue;
}
else
{
valueToBePassed = returnedValue.StringProperty;
}
NewFocusedClass.FocusedBehvaior(valueToBePassed);
}
}
public interface IExternalService
{
ReturnClass ExternalMethod();
}
public class NewFocusedClass
{
public virtual void FocusedBehvaior(string param)
{
}
}
public class ReturnClass
{
public string StringProperty { get; set; }
}
[TestClass]
public class ControllerTests
{
[TestMethod]
public void TestMethod()
{
//Given
var mockService = new Mock<IExternalService>();
mockService.Setup(s => s.ExternalMethod()).Returns((ReturnClass)null);
var mockFocusedClass = new Mock<NewFocusedClass>();
var actualParam = string.Empty;
mockFocusedClass.Setup(x => x.FocusedBehvaior(It.IsAny<string>())).Callback<string>(param => actualParam = param);
//when
var controller = new ControllerUnderTest(mockService.Object, mockFocusedClass.Object);
controller.MethodUnderTest();
//then
Assert.AreEqual("DefaultValue", actualParam);
}
}
Edit: Based on the suggestion in the comments to use "verify" instead of callback.
Easier way to verify the parameter value is by using strict MOQ behavior and a verify call on the mock after system under test is executed.
Modified test could look like below:
[TestMethod]
public void TestMethod()
{
//Given
var mockService = new Mock<IExternalService>();
mockService.Setup(s => s.ExternalMethod()).Returns((ReturnClass)null);
var mockFocusedClass = new Mock<NewFocusedClass>(MockBehavior.Strict);
mockFocusedClass.Setup(x => x.FocusedBehvaior(It.Is<string>(s => s == "DefaultValue")));
//When
var controller = new ControllerUnderTest(mockService.Object, mockFocusedClass.Object);
controller.MethodUnderTest();
//Then
mockFocusedClass.Verify();
}
"The only way I could think to do this is to use a mock for the class under test."
I think you should not mock class under test. Mock only external dependencies your class under test has. What you could do is to create a testable-class. It would be a class which derives from your CUT and here you can catch the calls to the another method and verify it's parameter later. HTH
Testable class in the example is named MyTestableController
Another method is named InternalMethod.
Short example:
[TestClass]
public class Tests
{
[TestMethod]
public void MethodUnderTest_WhenServiceReturnsNull_CallsInternalMethodWithDefault()
{
// Arrange
Mock<IService> serviceStub = new Mock<IService>();
serviceStub.Setup(s => s.ServiceCall()).Returns((ReturnedFromService)null);
MyTestableController testedController = new MyTestableController(serviceStub.Object)
{
FakeInternalMethod = true
};
// Act
testedController.MethodUnderTest();
// Assert
Assert.AreEqual(testedController.SomeDefaultValue, testedController.FakeInternalMethodWasCalledWithThisParameter);
}
private class MyTestableController
: MyController
{
public bool FakeInternalMethod { get; set; }
public string FakeInternalMethodWasCalledWithThisParameter { get; set; }
public MyTestableController(IService service)
: base(service)
{ }
internal override void InternalMethod(string someProperty)
{
if (FakeInternalMethod)
FakeInternalMethodWasCalledWithThisParameter = someProperty;
else
base.InternalMethod(someProperty);
}
}
}
The CUT could look something like this:
public class MyController : Controller
{
private readonly IService _service;
public MyController(IService service)
{
_service = service;
}
public virtual string SomeDefaultValue { get { return "SomeDefaultValue"; }}
public EmptyResult MethodUnderTest()
{
// We just found a bug in this method ...
// The method under test calls a service which returns an object.
ReturnedFromService fromService = _service.ServiceCall();
// It then calls an internal method passing a string property of this object
string someStringProperty = fromService == null
? SomeDefaultValue
: fromService.SomeProperty;
InternalMethod(someStringProperty);
return new EmptyResult();
}
internal virtual void InternalMethod(string someProperty)
{
throw new NotImplementedException();
}
}

moq callbase for methods that do not return value (void methods)

I am trying to mock my class that is under test, so that I can callbase on individual methods when testing them. This will allow me to test the method setup as callbase only, and all other methods (of the same class) called from within the test method will be mocked.
However, I am unable to do this for the methods that do not return a value. The intellisense just doesn't display the option of callbase, for methods that do not return value.
Is this possible?
The Service Class:
public class Service
{
public Service()
{
}
public virtual void StartProcess()
{
//do some work
string ref = GetReference(id);
//do more work
SendReport();
}
public virtual string GetReference(int id)
{
//...
}
public virtual void SendReport()
{
//...
}
}
Test Class setup:
var fakeService = new Mock<Service>();
fakeService.Setup(x => x.StartProcess());
fakeService.Setup(x => x.GetReference(It.IsAny<int>())).Returns(string.Empty);
fakeService.Setup(x => SendReport());
fakeService.CallBase = true;
Now in my test method for testing GetReference I can do this:
fakeService.Setup(x => x.GetReference(It.IsAny<int>())).CallBase();
but when i want to do the same for StartProcess, .CallBase is just not there:
fakeService.Setup(x => x.StartProcess()).CallBase();
it becomes available as soon as i make the method to return some thing, such a boolean value.
First of all, your mock will not work because methods on Service class are not virtual. When this is a case, Moq cannot intercept calls to insert its own mocking logic (for details have a look here).
Setting mock.CallBase = true instructs Moq to delegate any call not matched by explicit Setup call to its base implementation. Remove the fakeService.Setup(x => x.StartProcess()); call so that Moq can call base implementation.

Unit test that ensures method A called after method B

I have a code which interacts with some object and then should call finish() method on it.
void completeTransaction(PaymentTransaction transaction) {
recordTransaction(transaction.getId());
transaction.finish();
}
PaymentTransaction is some third-party class which behaviour after finish() is undefined — it may throw an exception or just fail silently.
I need to write a unit test which passes then and only then:
recordTransaction(transaction.getId()) called
transaction.finish() called
transaction.finish() called after recordTransaction(transaction.getId())
Test satisfying the above conditions should prohibit code like this:
void completeTransaction(PaymentTransaction transaction) {
transaction.finish();
recordTransaction(transaction.getId()); //oops
}
Test case for the first condition:
void testCompleteTransaction_TransactionRecorded() {
completeTransaction(transactionMock);
// assert that recordTransaction(transaction.getId())
// called with correct argument
completeTransaction(PaymentTransaction transaction)
}
For the second one:
void testCompleteTransaction_TransactionCompleted() {
completeTransaction(transactionMock);
// assert that transaction.finish() called
}
I wonder how can I enforce the 3rd condition via test case.
You could pass in a fake PaymentTransaction that overrides finish() and getId() such that finish() throws an exception if some internal flag isn't set when getId() is called.
public class FakePaymentTransaction {
private bool _getIdWasCalled = false;
public override void finish () {
if (!_getIdWasCalled) {
throw new Exception ("getId wasn't called first!");
}
}
public override /* your return type */ getId() {
_getIdWasCalled = true;
// Some other logic to return your specified return type
}
}
Now when you pass it into your SUT, you will see if the calls were made in the right order.
What you want is a mock that can verify the order of calls was as expected. You can roll your own for the specific case as suggested in James D'Angelo's answer or you could create a more generic one that works similarly.
Or you can use facilities supplied by a good mocking framework.
Mockito has, for example, an InOrder verifier that can verify the order of calls of mocked methods from a single mock or multiple mocks.
Your test case makes no sense:
Methods are called in the order you have them in the code:
In an Unit test you should not only call some methods, you should test for a correct result.
but if you want to have some fun:
public testNonsenseTest() {
int i = 0;
PaymentTransaction transaction = new PaymentTransaction();
int transactionId = transaction.getId());
recordTransaction(transactionId);
i++;
assertEquals(1, i);
transaction.finish();
i++;
assertEquals(2, i);
}