I'm having some troubles shadowing TimeZone.getDefault() using Robolectric since my AppTest.class is not using my static shadow mwthod in ShadowTimeZone.class.
AppTest.class
#RunWith(RobolectricTestRunner.class)
#Config(manifest = "../App/AndroidManifest.xml")
public class AppTest{
#Test
#Config(shadows = {ShadowTimeZone.class})
public void testTimeZone() {
String expectedTimeZoneId = "Europe/London";
TimeZone timeZone = TimeZone.getDefault();
assertThat(timeZone.getID(), equalTo(expectedTimeZoneId));
}
}
ShadowTimeZone.class
#Implements(TimeZone.class)
public class ShadowTimeZone {
#Implementation
public static TimeZone getDefault() {
return TimeZone.getTimeZone("Europe/London");
}
}
You don't need to use a shadow at all. Use TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")) before your test or in a #Before setup method.
If you still want to use a shadow, the actual signature for getDefault is public static synchronized, so you may need to add synchronized to your shadow method to match.
By default you can only shadow classes from android package. But you can add more classes to work with shadows. See https://stackoverflow.com/a/29641926/3619179
Related
#RunWith(MockitoJUnitRunner.Silent.class)
public class LoginActivityTest {
#InjectMocks
LoginActivity loginActivity;
private Pattern emailPattern;
#Before
public void createLogin(){
this.emailPattern = Patterns.EMAIL_ADDRESS;
}
#Test
public void checkValidation(){
mock(LoginActivity.class);
UserVO userVO = new UserVO();
userVO.setEmailID("invalid");
userVO.setPassword("a");
boolean b = loginActivity.validatesFields(userVO);
assertFalse(b);
}
}
this.emailPattern = Patterns.EMAIL_ADDRESS; This is creating null pointer object in MockitoJunitTestClass. But, when I run this on Activity it gets initialized properly.
Use PatternsCompat instead of Patterns
I was having a similar problem because it was just a simple test, but when I added #RunWith(AndroidJUnit4::class) the problem was fixed. Check if this is test that must run with Android resources or not.
I am a little confuse with your test:
You are mocking LoginActivity.class but not setting anything with that. I believe you want to do something like loginActivity = mock(LoginActivity.class); instead.
Also, your are mocking instead spying the class, so it won't access the real method in order to verify the flow of this method. In other words, your test is doing nothing in fact.
Finally, this emailPattern is never used on your test (probably it is used on you code), so I believe you want to mock it (I am supposing it). What I recommend you do is something like this:
#RunWith(MockitoJUnitRunner.Silent.class)
public class LoginActivityTest {
#Spy
#InjectMocks
private LoginActivity loginActivity;
#Mock
private OtherStuff otherStuff;
#Test
public void checkValidation(){
UserVO userVO = new UserVO();
userVO.setEmailID("invalid");
userVO.setPassword("a");
doReturn(Patterns.EMAIL_ADDRESS).when(otherStuff).doStuff();
boolean result = loginActivity.validatesFields(userVO);
assertFalse(result);
}
}
What I did here is just an example of unit test which is validating what validateFields() is doing. I suppose that inside this method you have some method on, what I name otherStuff, which calls a method that returns Patterns.EMAIL_ADDRESS, which is what you want to mock.
It would be really better if you insert the LoginActivity code to be more precise here, but I hope I helped you.
the below posted method in the code section contains a static method which is "with()". I want to test the code in below, so I coded the test of this method
as shown in the testing section.
i tried to test the method using both of "spy()" and "mock()" but the test fails alwyas.
please let me know how can I test a method returns void?
code
public RequestCreator requestCreatorFromUrl(String picUrl) {
return Picasso.with(mCtx).load(picUrl);
}
testing:
public class ValidationTest {
#Mock
private Context mCtx = null;
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Before
public void setUp() throws Exception {
mCtx = Mockito.mock(Context.class);
Assert.assertNotNull("Context is not null", mCtx);
}
#Test
public void whenRequestCreatorFromUrlTest() throws Exception {
Picasso picasso = Picasso.with(mCtx);
Picasso spyPicasso = spy(picasso);
Uri mockUri = mock(Uri.class);
RequestCreator requestCreator = Picasso.with(mCtx).load(mockUri);
RequestCreator spyRequestCreator = spy(requestCreator);
doReturn(spyRequestCreator).when(spyPicasso.load(mockUri));
//when(spyPicasso.load(mockUri)).thenReturn(spyRequestCreator);
RequestCreator actual = spyPicasso.load(mockUri);
Assert.assertEquals(requestCreator, actual);
}
Usually, if you end up using PowerMock, that’s a good sign that you most possibly are on the wrong way.
What if instead of directly referring to Picasso, you create a component, whose responsibility will be to load an image, let's say class ImageLoader. What will this give to you?
Separation of concerns: if tomorrow you decide to move to Glide, you shouldn't change each and every class where you were using Picasso, you will just change implementation of ImageLoader. Other components are non-wiser of these changes, because they are dependent on an abstraction, not on implementation
Seam: this will allow you easily mock dependencies in order to perform unit testing
This will be our abstraction:
interface ImageLoader {
RequestCreator load(String url);
}
Let’s provide an implementation:
class ImageLoaderImpl implements ImageLoader {
private final Picasso picasso;
public ImageLoaderImpl(Context context) {
this.picasso = Picasso.with(context);
}
#Override
public RequestCreator load(String url) {
return picasso.load(url);
}
}
Now, in your components whenever you need Picasso use ImageLoader instead.
Thus, your method becomes following:
public static RequestCreator requestCreatorFromUrl(String picUrl) {
return imageLoader.load(picUrl);
}
Then your test will look like this:
#Test
public void test() {
ImageLoaderImpl imageLoader = Mockito.mock(ImageLoaderImpl.class);
RequestCreator expected = Mockito.mock(RequestCreator.class);
String TEST_URL = "https://www.some.url/img.jpg";
when(imageLoader.load(TEST_URL)).thenReturn(expexted);
RequestCreator actual = clazzToTest.requestCreatorFromUrl(TEST_URL);
assertEquals(expected, actual);
}
No mocking of static method, no PowerMock needed.
From the Mockito's FAQ:
What are the limitations of Mockito
...
Cannot mock static methods
Use PowerMock instead. Here you will find the detailed instruction about how to mock the static methods.
Update
In order to apply the PowerMock to your test you need to:
Add #PrepareForTest at test class level:
#PrepareForTest(Picasso.class)
public class ValidationTest {
...
}
Call PowerMockito.mockStatic() to mock a static class
PowerMockito.mockStatic(Picasso.class);
Just use Mockito.when() to setup your expectation:
Mockito.when(Picasso.with(mCtx)).thenReturn(requestCreator);
The same set of steps is applicable for the RequestCreator.class.
P.S. I can make mistakes because I do not know the API of 3rd party library you use.
How to verify a void method call in Robolectric test case where as no data coming out the called method.
What to assert in this case? Below given an example of the requirement.
public class SampleClass(){
final String TAG = SampleClass.class.getSimpleName();
public void log(){
Log.d(TAG, "Entry Loggd");
}
}
#Test
public void logEntry_test(){
SampleClass sc = new SampleClass();
sc.log();
// What to assert here to verify this log method
}
First off, good on you for writing tests!!! There are a few ways to go about testing that an internal logger is called. It's equally as important to understand what you're looking to test. Testing that a class is logging a specific message is most likely a fragile test, so be fore-warned that you probably don't need it.
Method #1: Using Robolectric
Robolectic documentation doesn't lend itself to answering basic questions, but its codebase is very well documented with its tests. A basic understanding of its principles and how shadows work can get you a long way. ShadowLog tests lay the ground work to this solution.
#RunWith(RobolectricTestRunner.class)
public class SampleClassTest {
#Test
public void log_writesExpectedMessage() {
new SampleClass().log();
ShadowLog.LogItem lastLog = ShadowLog.getLogs().get(0);
assertThat(lastLog.msg).isEqualTo("some message");
// or
assertThat(lastLog.msg).isNotNull();
}
}
Tests using Robolectric v3.1.2
Add the following to your build.gradle file:
testCompile 'org.robolectric:robolectric:3.1.2'
Method #2: Making use of Abstractions
If your sample class derives from an Android class (Activity, Fragment, Application, etc), then using android.util.Log makes sense, but bear in mind that your test will need to be a Robolectric or AndroidInstrumented test. If your SampleClass is just some POJO, then using a simple logging framework may make your testing efforts easier. For example, using Jake Wharton's Timber, your class and test can be written as follows:
import timber.log.Timber;
public class SampleClass {
void log() {
Timber.d("some message");
}
}
// SampleClassTest.java
public class SampleClassTest {
// setting up a Tree instance that we define below
TestTree testTree = new TestTree();
#Test
public void log_writesExpectedMessage() {
// setting up Timber to us the test classes log writer
Timber.plant(testTree);
// invoke the logging function
new SampleClass().log();
// assert
assertThat(testTree.lastMessage).isEqualTo("some message");
}
private class TestTree extends Timber.Tree {
private String lastMessage;
#Override
protected void log(int priority, String tag, String message, Throwable t) {
lastMessage = message;
}
}
}
Good luck, happy testing!
In my understanding you want to mock static methods. I guess, using static mocks are not the most elegant way to testing. Better to use an abstraction as recommended by abest. Although, it can be done with PowerMock.
As per the official guide for Roboelectric 1.X (at http://pivotal.github.io/robolectric/customizing.html), the way to use your own shadow class is to create your own test runner and override the appropriate method OR by using #Roboelectric.bindShadowClass (see below).
However, things have changed for 2.X and I can't seem to find the new way to do this.
Anyone know how to use a custom shadow class without changing the
public class CustomTestRunner extends RobolectricTestRunner {
public CustomTestRunner(Class testClass) throws InitializationError {
super(testClass);
}
#Override public void beforeTest(Method method) {
Robolectric.bindShadowClass(ShadowBitmapFactory.class);
Robolectric.bindShadowClass(ShadowDrawable.class);
Robolectric.bindShadowClass(ShadowGeocoder.class);
}
}
You can use the new Robolectric 2.0 Config annotation type to bind custom Shadow classes.
For example you annotate a test method like this:
#Config( shadows = { MyShadow.class, MyOtherShadow.class } )
public void testSomething {
...
}
Best Regards,
Seb
This question is probably exact duplicate of this one
Pass parameter to constructor with Guice
Difference is that I use roboguice for android, not just Guice, so answers there does not work for me.
Question is - how can I pass initialize parameters into created object? I.e. I have injected interface which should be initialize with some parameter which roboguice does not know.
What I see in link I provide, I should create factory interface and register it like this
void configure(Binder binder) {
binder.install(new FactoryModuleBuilder()
.implement(FooInterface.class, Foo.class)
.build(FooFactory.class));
}
But I can't find FactoryModuleBuilder class. I use Intellij IDEA, it can show me every class which I can access at current place and I can be 100% sure that there is no classes which starts with 'Factory' word.
How can I create my factory using roboguice?
UPDATED
I forgot to download guice-assistedinject. But still I can't figure out where should I register this factory.
UPDATE 2
Why I need that? Because there should be situation where some abstraction has dependency which could not be resolved by Roboguice. This dependency could be any type, even simple string or number.
In my case I have NumberPicker control on UI and I want to move all UI specific tasks in MyNumberPickerWrapper class. And when I create this wrapper I inject its dependency (this control) through constructor.
It's not the point if I am right with such approach, but that there could be a plenty of another more applicable example where constructor injection needed and this injected classes could not be created by Roboguice
I followed the steps of the answer given in Pass parameter to constructor with Guice and did slight modifications to run it under roboguice. Works completely fine for me.
add guice-assistinject library to gradle script
dependencies { compile 'com.google.inject.extensions:guice-assistedinject:4.+' }
Create Factory interface that with create method that accepts parameters the object constructor requires and returns object's interface
public interface ICustomObjectFactory {
ICustomObject create(String queueName);
}
Add #Inject annotation to constructor of the object and #Assisted annotation to each parameter coming from factory.
public class CustomObject implements ICustomObject {
protected String name;
#Inject
public CustomObject(#Assisted String name){
this.name = name;
}
}
Add binding into the Module that you are using
public class SomeModule extends AbstractModule {
#Override
protected void configure() {
install(new FactoryModuleBuilder()
.implement(ICustomObject.class, CustomObject.class)
.build(ICustomObjectFactory.class));
}
}
Inject factory and create instances of your object
public class SomeClass {
#Inject ICustomObjectFactory factory;
public SomeClass () {
ICustomObject first = this.factory.create("first");
ICustomObject second = this.factory.create("second");
}
}
I faced this same problem and I succeed thanks to Pavel's answer. I only have had to struggle with some errors, and I don't know if it's due to the versions of the libraries used, but for me didn't work without modifying the annotation of the constructor, replacing #Inject by #AssistedInject. With that, the code of the class that implements the interface looks like this.
public class CustomObject implements ICustomObject {
protected String name;
#AssistedInject
public CustomObject(#Assisted String name){
this.name = name;
}
}