I have this production code in my Presenter:
#UiThread
public void tryToReplaceLogo(String emailInitiallySearchedFor, String logoUrl) {
if(isTheEmailWeAskedApiForStillTheSameAsInTheInputField(emailInitiallySearchedFor)){
if (!TextUtils.isEmpty(logoUrl)) {
downloadAndShowImage(logoUrl);
} else {
view.displayDefaultLogo();
}
}
}
public void downloadAndShowImage(String url) {
final Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
view.displayLogoFromBitmap(bitmap);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
Picasso.with(view.getViewContext()).load(url).resize(150, 150).centerInside().into(target);
}
And this unit test for it:
#Test
public void testDisplayLogoIfValidUrlReturnedAndEmailEnteredIsTheSame() throws Exception {
when(loginView.getUserName()).thenReturn(VALID_EMAIL);
when(loginView.getViewContext()).thenReturn(context);
loginLogoFetcherPresenter.onValidateEmailEvent(createSuccessfulValidateEmailEvent(VALID_EMAIL));
waitForAsyncTaskToKickIn();
verify(loginView).displayLogoFromBitmap((Bitmap) anyObject());
}
However, the displayLogoFromBitmap method is never called so my test fails. I need to mock the Target dependency to invoke the onBitmapLoaded method but I don't know how.
Possibly I need to create a static inner class that implements Target so that I can set a Mocked implementation of that in my tests, but how do I invoke the onBitmapLoaded method on the mock?
EDIT:
I have a setter field for Picasso in my LoginPresenter now. In production, (as I am using AndroidAnnotations), I instantiate it in
#AfterInject
void initPicasso() {
picasso = Picasso.with(context):
}
In my test, I mock Picasso like so:
#Mock
Picasso picasso;
#Before
public void setUp() {
picasso = mock(Picasso.class, RETURNS_DEEP_STUBS);
}
(I don't remember why, but I can't use Mockito 2 at this point. It was some incompatibility with something, I think)
In my test case, I got to this point and I don't know what to do:
#Test
public void displayLogoIfValidUrlReturnedAndEmailEnteredIsTheSame() throws Exception {
when(loginView.getUserName()).thenReturn(VALID_EMAIL);
when(loginView.getViewContext()).thenReturn(context);
when(picasso.load(anyString()).resize(anyInt(), anyInt()).centerInside().into(???)) // What do I do here?
loginLogoFetcherPresenter.onValidateEmailEvent(createSuccessfulValidateEmailEvent(VALID_EMAIL));
waitForAsyncTaskToKickIn();
verify(loginView).displayLogoFromBitmap((Bitmap) anyObject());
}
I need to mock the Target dependency
No; do not mock the system under test. Target is as much a part of that system as anything; you wrote the code for it, after all. Remember, once you mock out a class, you commit to not using its implementation, so trying to mock Target to invoke onBitmapLoaded is missing the point.
What's going on here is that you're passing Target—which is real code you wrote that is worth testing—into Picasso, which is external code you didn't write but do depend on. This makes Picasso the dependency worth mocking, with the caveat that mocking interfaces you don't control can get you into trouble if they change (e.g. a method turns final).
So:
Mock your Picasso instance, and the RequestCreator instance Picasso returns when it loads. RequestCreator implements the Builder pattern, so it's a prime candidate for Mockito 2.0's RETURNS_SELF option or other Builder pattern strategies.
Pass the Picasso instance into your system under test, rather than creating it using Picasso.with. At this point you may not need to stub LoginView.getViewContext(), which is a good thing as your test can interact less with hard-to-test Android system classes, and because you've further separated object creation (Picasso) from business logic.
Use an ArgumentCaptor in your test to extract out the Target method that was called on RequestCreator.into.
Test the state of the system before the async callback returns, if you'd like. It's optional, but it's definitely a state your system will be in, and it's easy to forget to test it. You'd probably call verify(view, never()).onBitmapLoaded(any()).
Call target.onBitmapLoaded yourself. You have the target instance at this point, and it should feel correct to explicitly call your code (that is written in your system-under-test) from your test.
Assert your after-callback state, which here would be verify(view).onBitmapLoaded(any()).
Note that there is an existing test helper called MockPicasso, but it seems to require Robolectric, and I haven't reviewed its safety or utility myself.
Related
So, I am trying to unit test a class in various scenarios. We use JUnit V 4.
I have a setUp method wherein i reStub the mock to return an expected mock Value.
I have 4 tests : test1-test4. test1,test2 work fine with the expected mocked value configured in perTestSetup method.
Test t3 needs MockClass to throw an exception, so i configure it seperately in t3. Now t3 works fine as the mock throws the exception as expected.
But when perTestSetup tries to reset the mock to return mockResult before running test4, it fails and throws the same Runtime exception configured in t4. I also tried reset() before mocking in perTestSetup(). But that too fails similarly.
What am i missing here?
#Before
public void perTestSetup(){
when(MockClass.functionCall(...)).thenReturn(mockResult);
}
#Test
public void test1(){
}
#Test
public void test2(){
}
#Test
public void test3(){
when(MockClass.functionCall(...)).thenThrow(new RuntimeExcption());
...
}
#Test
public void test4(){
}
Your perTestSetup() method isn't doing what you think it is doing. The #Before annotation means the test environment will run this method once, before doing any of the tests, rather than once per test. Before I finished reading your question, I was actually itching to advise you to rename this method to simply setup(), as that would be a more accurate description.
Options:
Change the annotation to #BeforeEach, which would then change the behaviour to do what you think it should currently be doing. However, this would be inefficient as in the second two tests you will be defining behaviour and then immediately redefining it.
What do the parameters look like in your functionCall(...)? It may be possible to define two separate behaviours in your single #Before setup() method, i.e.
when(MockClass.functionCall(good values)).thenReturn(mockResult);
when(MockClass.functionCall(bad values)).thenThrow(new RuntimeException());
In each test, call functionCall() with the relevant values for that that particular test.
If the parameters in functionCall() do not readily accommodate the previous approach, consider making two separate instantiations of MockClass, something like
MockClass successfulMockClass = new mock(MockClass.class);
when(successfulMockClass()).thenReturn(mockResult);
MockClass unsuccessfulMockClass = new mock(MockClass.class);
when(unsuccessfulMockClass()).thenThrow(new RuntimeException());
In your tests, call on the relevant mocked object depending on what input you are testing against.
Without being able to see the details of your class, I suspect the second option is what I would go for. It may be worth trying all three to see which feels most intuitive for you, though.
I am trying to write a Unit Tests to a legacy code using Mockito.
But I am not able to understand how do I mock it. Can some please help.
The real problem I am facing is actually I am not able to decide how to make a decision on what exactly is to be mocked? Below is the code. I have looked at numerous videos on YouTube and read many Mockito Tutorials but all of them seem to be guiding mostly about how to use the Mockito Framework.
The basic idea of what to Mock is still unclear. Please guide if you have a better source. I do understand that the code showed below does not really showcase the best coding practice.
public class DataFacade {
public boolean checkUserPresent(String userId){
return getSomeDao.checkUserPresent(userId);
}
private SomeDao getSomeDao() {
DataSource dataSource = MyDataSourceFactory.getMySQLDataSource();
SomeDao someDao = new SomeDao(dataSource);
}
}
Well, a Unittest, as the name implies, tests a unit. You should mock anything that isn't part of that unit, especially external dependencies. For example, a DAO is normally a good example for something that will be mocked in tests where the class under tests uses it, because otherwise you would really have actual data access in your test, making it slower and more prone to failure because of external reasons (for example, if your dao connects to a Datasource, that Datasource's target (for example, the database) may be down, failing your test even if the unit you wanted to test is actually perfectly fine). Mocking the DAO allows you to test things independently.
Of course, your code is bad. Why? You are creating everything in your method by calling some static factory method. I suggest instead using dependency injection to inject the DAO into your facade, for example...
public DataFacade(SomeDao someDao) {
this.someDao = someDao;
}
This way, when instantiating your DataFacade, you can give it a dao, which means, in your test you can give it a mock, for example...
#Test
public void testSomething() {
SomeDao someDaoMock = Mockito.mock(SomeDao.class);
DataFacade toTest = new DataFacade(someDaoMock);
...now you can prepare your mock to do something and then call the DataFace method
}
Dependency injection frameworks like Spring, Google Guice, etc. can make this even easier to manage, but the first step is to stop your classes from creating their own dependencies, but let the dependencies be given to them from the outside, which makes the whole thing a lot better.
You should "mock" the inner objects that you use in your methods.
For example if you write unit tests for DataFacade->checkUserPresent, you should mock the getSomeDao field.
You have a lot of ways to do it, but basically you can make getSomeDao to be public field, or get it from the constructor. In your test class, override this field with mocked object.
After you invoke DataFacade->checkUserPresent method, assert that checkUserPresent() is called.
For exmaple if you have this class:
public class StudentsStore
{
private DbReader _db;
public StudentsStore(DbReader db)
{
_db = db;
}
public bool HasStudents()
{
var studentsCount = _db.GetStudentsCount();
if (studentsCount > 0)
return true;
else
return false;
}
}
And in your test method:
var mockedDb = mock(DbReader.class);
when(mockedDb.GetStudentsCount()).thenReturn(1);
var store = new StudentsSture(mockedDb);
assertEquals(true,store.HasStudents());
I am trying to write unit test for a method which uses an instance of cache as below
public void method(String abc) {
....
....
Cache cache = CacheFactory.getAnyInstance();
....
....
}
I know mocking is the way to resolve this dependency on cache. I am new to mocking and using mockito and not sure on how to pass the mocked cache to the method.
#Mock
Cache cache;
#Test
public void testMethod(){
doReturn(cache).when(CacheFactory.getAnyInstance());
method("abc");
}
The above is what I've tried and got the error.
If you are testing some code path in your application component that calls CacheFactory.getAnyInstance() (such as method("abc")?), then you must ensure that the method gets a reference to the mock Cache another way since you cannot mock a static method on a class (i.e. getAnyInstance() on CacheFactory), at least not without some help from a framework like PowerMock. For example...
public class ExampleApplicationComponent {
public void methodUnderTest(String value) {
...
Cache hopefullyAMockCacheWhenTesting = CachFactory.getAnyInstance();
...
// do something with the Cache...
}
}
Of course, this will fail. So you need to restructure your code a bit...
public class ExampleApplicationComponent {
public void methodUnderTest(String value) {
...
Cache cache = fetchCache();
...
// do something with the (mock) Cache...
}
Cache fetchCache() {
return CacheFactory.getAnyInstance();
}
}
Then in you test case in your test class...
public class ExampleApplicationComponentTest {
#Mock
private Cache mockCache;
#Test
public void methodUsesCacheProperly() {
ExampleApplicationComponent applicationComponent =
new ExampleApplicationComponent() {
Cache fetchCache() {
return mockCache;
}
};
applicationComponent.method("abc");
// assert appropriate interactions were performed on mockCache
}
}
So as you can see, you can override the fetchCache() method in your anonymous ExampleApplicationComponent subclass within you test case to return the mock Cache. Also note, the fetchCache() method was deliberately made "package-private" to limit it's accessibility to primarily the test class (since test classes usually and should reside in the same package as the class under test). This prevents the fetchCache method from escaping and becoming part of your API. While other classes in the same package can access the method of an instance of the ExampleApplicationComponent class, you at least retrain control over that usage (and of course there is not substitute for good documentation).
To see other examples of this in practice, have a look as Spring Data GemFire's CacheFactoryBeanTest class (for instance, and specifically), which does exactly what I described above using Mockito.
Hope this helps.
Cheers!
-John
I was ble to do this with the help of PowerMockito below is the code
mockStatic(CacheFactory.class);
when(CacheFactory.getAnyInstance()).thenReturn(cache);
method("abc");
verifyStatic();
CacheFactory.getAnyInstance();
I have inherited some code that isn't tested and which loads a resource using a method like :
SomeClass.class.getClassLoader().getResource("somefile");
I've written the following test but there are 0 interactions with the Mock class loader I've created. Can anyone comment on whether this type of test is possible.
public enum SomeClass {
INSTANCE;
public boolean someMethod() {
URL pathToLicense = SomeClass.class.getClassLoader().getResource("somefile");
return false;
}
}
#Test
public void testLicenseWorkflow(){
ClassLoader cl = PowerMockito.mock(ClassLoader.class);
File f = new File("someFile");
assertTrue(f.exists());
logger.info(f.getCanonicalPath() );
when(cl.getResource("somefile")).thenReturn(f.toURL());
verify(cl).getResource("somefile");
assertTrue(SomeClass.INSTANCE.someMethod());
}
Update - Adding a resources via Classloader
I've also tried the following but the someMethod this doens't seem to work either
new URLClassLoader(((URLClassLoader) SomeClass.INSTANCE.getClass().getClassLoader()).getURLs()) {
#Override
public void addURL(URL url) {
super.addURL(url);
logger.info("Calling add URL");
}
}.addURL(f.toURI().toURL());
You are not passing cl to anything. You prepare a mock for a classloader but then proceed to load the resource with another classloader, the one that loaded SomeClass. That is why you have 0 interactions in your mock.
And about your first question, it is possible if somehow you pass your mocked classloader to the method that actually loads the resource. For example, something like
public boolean someMethod(Classloader loader) {
URL pathToLicense = loader.getResource("somefile");
return false;
}
But I have to say that IMO, this test is not very useful, you should be mocking your own components, not java classes. If your goal mocking the classloader is to inject a different file when testing, a better approach is to change your code to receive a Stream and inject a stream connected to the file in production and in testing inject a stream connected to an element in memory.
In other words, resources make for bad testing when they need to be changed at test time
I'm trying to unit test a custom ValueResolver (Automapper) but am running into problems because the method it forces me to override is not exposed directly in the custom object we must create. I override the protected method "ResolveCore" but the only public method exposed is "Resolve" which expects a complex "ResolutionResult" automapper object as it's input. In the vein of true unit testing I want to test this object / method in isolation to anything else and don't really want to go the route of firing up automapper with mappings to do this test. Likewise it's not possible to Mock "ResolutionResult" and it seems a very complex object to setup for each test (again requiring creation / association of other Automapper objects).
The only (less than ideal) solution I can come up with (and have seen suggested when Googling for a solution) is to stub a public method inside the class that exposes the protected overriden method. If we must go down this route then so be it, but has anyone else got a better solution that tests the method call in isolation doesn't require a modification of the object we are trying to test?
Example code:
public class CustomResolver : ValueResolver<Supplier, string>
{
protected override string ResolveCore(Custom source)
{
return string.Format("{0} {1}", source.Name, source.Descripton);
}
public string UnitTestStub(Custom source)
{
return ResolveCore(source);
}
}
I wouldn't place a public stub in your class. Instead, I'd just create a simple subclass in my unit test assembly that exposes the call I wanted to test:
public class TestCustomResolver : CustomResolver
{
public string TestResolveCore(Custom source)
{
return this.ResolveCore(source);
}
}
Some of this depends on the unit testing framework you're using too. For example, you could use the InternalsVisibleTo() attribute to expose your internals to your unit tests. However, I would lean towards a simple subclass in your unit tests.