I gave to Google Guice the responsibility of wiring my objects. But, how can I test if the bindings are working well?
For example, suppose we have a class A which has a dependence B. How can I test that B is injected correctly?
class A {
private B b;
public A() {}
#Inject
public void setB(B b) {
this.b = b
}
}
Notice that A hasn't got a getB() method and I want to assert that A.b isn't null.
For any complex Guice project, you should add tests to make sure that the modules can be used to create your classes. In your example, if B were a type that Guice couldn't figure out how to create, then Guice won't be able to create A. If A wasn't needed to start the server but was needed when your server was handling a request, that would cause problems.
In my projects, I write tests for non-trivial modules. For each module, I use requireBinding() to declare what bindings the module requires but doesn't define. In my tests, I create a Guice injector using the module under test and another module that provides the required bindings. Here's an example using JUnit4 and JMock:
/** Module that provides LoginService */
public class LoginServiceModule extends AbstractModule {
#Override
protected void configure() {
requireBinding(UserDao.class);
}
#Provides
LoginService provideLoginService(UserDao dao) {
...
}
}
#RunWith(JMock.class)
public class LoginServiceModuleTest {
private final Mockery context = new Mockery();
#Test
public void testModule() {
Injector injector = Guice.createInjector(
new LoginServiceModule(), new ModuleDeps());
// next line will throw an exception if dependencies missing
injector.getProvider(LoginService.class);
}
private class ModuleDeps extends AbstractModule {
private final UserDao fakeUserDao;
public ModuleDeps() {
fakeUserDao = context.mock(UserDao.class);
}
#Override
protected void configure() {}
#Provides
Server provideUserDao() {
return fakeUserDao;
}
}
}
Notice how the test only asks for a provider. That's sufficient to determine that Guice could resolve the bindings. If LoginService was created by a provider method, this test wouldn't test the code in the provider method.
This test also doesn't test that you binded the right thing to UserDao, or that UserDao was scoped correctly. Some would argue that those types of things are rarely worth checking; if there's a problem, it happens once. You should "test until fear turns to boredom."
I find Module tests useful because I often add new injection points, and it's easy to forget to add a binding.
The requireBinding() calls can help Guice catch missing bindings before it returns your injector! In the above example, the test would still work if the requireBinding() calls were not there, but I like having them because they serve as documentation.
For more complicated modules (like my root module) I might use Modules.override() to override bindings that I don't want at test time (for instance, if I want to verify that my root object to be created, I probably don't want it to create an object that will connect to the database). For simple projects, you might only test the top-level module.
Note that Guice will not inject nulls unless the field as annotated with #Nullable so you very rarely need to verify that the injected objects are non-null in your tests. In fact, when I annotate constructors with #Inject I do not bother to check if the parameters are null (in fact, my tests often inject null into the constructor to keep the tests simple).
Another way to test your configuration is by having a test suite that tests your app end-to-end. Although end-to-end tests nominally test use cases they indirectly check that your app is configured correctly, (that all the dependencies are wired, etc etc). Unit tests on the other hand should focus exclusively on the domain, and not on the context in which your code is deployed.
I also agree with NamshubWriter's answer. I'm am not against tests that check configuration as long as they are grouped in a separate test suite to your unit tests.
IMHO, you should not be testing that. The Google Guice guys have the unit tests to assert that the injections work as expected - after all, that's what Guice is designed to do. You should only be writing tests for your own code (A and B).
I don't think you should test private members being set. Better to test against the public interface of your class. If member "b" wouldn't be injected, you'll probably get a NullPointerException executing your tests, which should be plenty of warning.
Related
A set of tests should be run on every microservice. Current solution is to have an abstract class and extend in every service, providing the necessary properties in abstract getters.
public abstract class AbstractTest {
#LocalServerPort
protected int serverPort;
protected abstract String getPath();
#Test
void someTest() {}
#Test
void conditionalTest() {}
}
#SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
classes = {...})
#ActiveProfiles(...) // etc
public class MyTest extends AbstractTest {
// ... implement getPath()
// tests from parent will be executed
}
The goal:
Ditch inheritance and have the AbstractTest's logic get executed automatically with conditional #Test execution based on beans/properties etc.
The possible solution:
A concrete class with all the tests or some sort of Configuration/TestFactory to create the necessary tests. It should take into account available properties and beans to determine which tests to run.
The problem:
How can those tests (created in runtime) be discovered and registered for execution?
How to inject all the properties that are part of the current context of the #SpringBootTest?
Failed attempts:
TestInstanceFactory extension doesn't seem to be the solution as it requires an instance of the class which it annotates.
Using the Launcher API seems overkill, and also doesn't seem to work, since the library class won't be created with the Spring context configs.
using cglib and a base class Spring Contract-style is not a desirable solution
Ideally I don't want the client of this lib to implement/create anything, so abstract String getPath(); would be a test.lib.path property, and if it's present, a test from the library which uses it will run.
Any thoughts on this would be great, because right now this just seems impossible to me.
What is the reason to have the inheritance for tests?
In case you need to share some common logic within the tests you may try JUnit features (custom rules/extensions), for example
For junit < 5.x.x #Rule functionality https://junit.org/junit4/javadoc/4.12/org/junit/rules/TemporaryFolder.html https://stackoverflow.com/a/34608174/6916890
For junit >= 5.x.x (jupiter) there is an extension API
https://junit.org/junit5/docs/current/user-guide/#writing-tests-built-in-extensions-TempDirectory
My team owns a library that provides components that must be referencable by code that consumes the library. Some of our consumers use Spring to instantiate their apps; others use Guice. We'd like some feedback on best-practices on how to provide these components. Two options that present themselves are:
Have our library provide a Spring Configuration that consumers can #Import, and a Guice Module that they can install.
Have our library provide a ComponentProvider singleton, which provides methods to fetch the relevant components the library provides.
Quick sketches of what these would look like:
Present in both approaches
// In their code
#AllArgsConstructor(onConstructor = #__(#Inject))
public class ConsumingClass {
private final FooDependency foo;
...
}
First approach
// In our code
#Configuration
public class LibraryConfiguration {
#Bean public FooDependency foo() {...}
...
}
---
public class LibraryModule extends AbstractModule {
#Provides FooDependency foo() {...}
...
}
========================
========================
// In their code
#Configuration
#Import(LibraryConfiguration.java)
public class ConsumerConfiguration {
// Whatever initiation logic they want - but, crucially, does
// *not* need to define a FooDependency
...
}
---
// *OR*
public class ConsumerModule extends AbstractModule {
#Override
public void configure() {
// Or, simply specify LibraryModule when creating the injector
install(new LibraryModule());
...
// As above, no requirement to define a FooDependency
}
}
Second approach
// In our code
public class LibraryProvider {
public static final INSTANCE = buildInstance();
private static LibraryProvider buildInstance() {...}
private static LibraryProvider getInstance() {return INSTANCE;}
}
========================
========================
// In their code
#Configuration
public class ConsumerConfiguration {
#Bean public FooDependency foo() {
return LibraryProvider.getInstance().getFoo();
}
...
}
// or equivalent for Guice
Is there an accepted Best Practice for this situation? If not, what are some pros and cons of each, or of another option I haven't yet thought of? The first approach has the advantage that consumers don't need to write any code to initialize dependencies, and that DI frameworks can override dependencies (e.g. with mocked dependencies for testing); whereas the second approach has the advantage of being DI-framework agnostic (if a new consumer wanted to use Dagger to instantiate their app, for instance, we wouldn't need to change the library at all)
I think the first option is better. If your library has inter-dependencies between beans then the code of #Configuration in case of spring in the second approach) will be:
Fragile (what if application doesn't know that a certain bean should be created)
Duplicated - this code will appear in each and every consumer's module
When the new version of your library gets released and a consumer wants to upgrade- there might be changes in consumer's configuration ( the lib might expose a new bean, deprecate or even remove some old stuff, etc.)
One small suggestion:
You can use Spring factories and then you don't even need to make an #Import in case of spring boot. just add a maven dependency and it will load the configuration automatically.
Now, make sure that you work correctly with dependencies in case of that approach.
Since you code will include both spring and Juice dependent code, you'll add dependencies on both for your maven/gradle module of the library. This means, that consumer that uses, say, guice, will get all the spring stuff because of your library. There are many ways to overcome this issue depending on the build system of your choice, just want wanted to bring it up
I am fairly new to mockito framework. I've been reading upon multiple tutorials in regards to it. One of them I was following is this: https://www.tutorialspoint.com/mockito/mockito_first_application.htm
There is a statement creating a mock of Stock Service.
In this example, we've created a mock of Stock Service to get the dummy price of some stocks
My question is Stock Service is a real service class or mock service class you have to manually stand up for mimicking the real service class. I am a bit confused. Having basic understanding of junit framework. What I had practiced before was if there is a service class Foo then I used actual class that provides all the exposed methods.
public class Foo {
public Foo() { } // construtor
public String returnAddress(String userId) {
// ...
return dataAccesobj.getAddress(userId);
}
}
Calling foo.returnAddress(..) in unit test if I remember right.
The reason I am asking this question is while I was working with mockitoto create a test method for a class, I ran into a unique(?) challenge.
I started with a real service class which depends on its super class constructor to return its instance. The challenge I ran into was this super class constructor initiates DB connection and loading/parsing properties files which I do not need for my test. I was thinking about how to prevent DB connection and loading/reading prop files....
I thought I read from one of mockito tutorials you can isolate testing without having such services. I tried with #Mock and #Spy (not fully understanding well still what they are for..) but it didn't make a difference for output (maybe I misused those annotations).
So what I did was actually creating fake/mock class out of real service class (e.g. Foo) by simply copying it and renamed it as FooMock and put it in src/test/java folder in where unit test class is running from. I kept the mock class exactly same as the real service class except taking out unwanted logic such as db connection or loading/reading prop file for env specific. By doing that I was able to test one of exposed methods that read ldap directory...
I am sorry I got digressed but hope my point is clear at this point. I am not sure the way I handled this situation is right or wrong. I'd appreciate experienced engineers would clarify the way I handled the matter is acceptable in mockito way or not. If not, then plz advise me best way to handle it.
With Mockito,
a mock is an implementation of a wrapper class.
The mock object "wraps" the target of the mock
(the service in your example)
and allows you to define functionality of each method.
There are two mocked functionality options with Mockito;
call the wrapped method and don't call the wrapped method.
I don't know when it would make sense to call the wrapped method,
so I always use don't call the wrapped method.
After you create the mock,
use the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) method to mock functionality.
Edit: some more info.
I will assume that you are using junit v4.
The details of this will differ based on the the junit major release number,
but the actual work will be the same.
Use annotations to define your Mock objects (#Mock),
except in a few special cases.
This will create mocks of non-final classes,
abstract classes,
and interfaces.
Create a "before-test" method using the #Before annotation;
I traditionally name this method preTestSetup,
but the actual name does not matter.
Call MockitoAnnotations.initMocks(this) as the first line of code
in the "before-test" method.
This will find the #Mock annotations and instantiate a mock for each.
Use the ReflectionTestUtils.setField method to inject the mocks into your object (assuming that you don't have setter methods,
which I traditionally don't like).
Define the mocked functionality of each method using the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) technique.
Here is some example code
(caveat:
this should be fully functional,
but I did not compile it):
public interface MyService
{
String blammy(SomeParameter parameter);
}
public class UsesMyService
{
#Autowired
private MyService myService;
public String kapow(final SomeParameter parameter)
{
return myService.blammy(parameter);
}
}
public class UnitTestUsesMyService
{
private UsesMyService classToTest;
#Mock
private MyService mockMyService;
#Mock
private SomeParameter mockSomeParameter;
#Before
public void preTestSetup()
{
MockitoAnnotations.initMocks(this);
classToTest = new UsesMyService();
doReturn("Blam").when(mockMyService).blammy(mockSomeParameter);
ReflectionTestUtils.setField(
classToTest,
"myService",
mockMyService);
}
#Test
public void kapow_allGood_success()
{
final String actualResult;
actualResult = classToTest.kapow(mockSomeParameter);
assertNotNull(actualResult); // Not strictly necessary.
assertEquals(
"Blam",
actualResult);
}
}
I need to create tests for some class. This class in main project (src/main/java/..) is injected easily into another classes, since I have custom ResourceConfig class which declares which packages have to be scanned to seek for service classes.
Now I created test directories (in src/test/java/..) and created a class, something like:
public class TheMentionedClassIntegrationTest {
#Inject
private TheMentionedClass theMentionedClass ;
#Test
public void testProcessMethod() {
assertNotNull(theMentionedClass);
}
}
But the problem is that whatever I do the class is always null. In another tests in the project I was using JerseyTest class. So I tried to do the same here, extend TheMentionedClassIntegrationTest with JerseyTest, override configure method, create my private ResourceConfig class which registers Binder (default for whole project) and register TheMentionedClassIntegrationTest as well.
It didnt work. I did many different attempts but none of them were successfull. I think working with HK2 is extremly difficult, there is no good documentation or so..
Do you guys have an idea how to inject TheMentionedClass into the test class? Maybe my approach is wrong?
Thanks!
The easiest thing to do is to just create the ServiceLocator and use it to inject the test class, as see here. For example
public class TheMentionedClassIntegrationTest {
#Inject
private TheMentionedClass theMentionedClass;
#Before
public void setUp() {
ServiceLocator locator = ServiceLocatorUtilities.bind(new YourBinder());
locator.inject(this);
}
#Test
public void testProcessMethod() {
assertNotNull(theMentionedClass);
}
}
You could alternatively use (make) a JUnit runner, as seen here.
For some other ideas, you might want to check out the tests for the hk2-testing, and all of its containing projects for some use case examples.
Here's how we are using Guice in a new application:
public class ObjectFactory {
private static final ObjectFactory instance = new ObjectFactory();
private final Injector injector;
private ObjectFactory() throws RuntimeException {
this.injector = Guice.createInjector(new Module1());
}
public static final ObjectFactory getInstance() {
return instance;
}
public TaskExecutor getTaskExecutor() {
return injector.getInstance(TaskExecutor.class);
}
}
Module1 defines how the TaskExecutor needs to be constructed.
In the code we use ObjectFactory.getInstance().getTaskExecutor() to obtain and the instance of TaskExecutor.
In unit tests we want to be able to replace this with a FakeTaskExecutor essentially we want to get an instance of FakeTaskExecutor when ObjectFactory.getInstance().getTaskExecutor() is called.
I was thinking of implementing a FakeModule which would be used by the injector instead of the Module1.
In Spring, we would just use the #Autowired annotation and then define separate beans for Test and Production code and run our tests with the Spring4JunitRunner; we're trying to do something similar with Guice.
Okay, first things first: You don't appear to be using Guice the way it is intended. Generally speaking, you want to use Guice.createInjector() to start up your entire application, and let it create all the constructor arguments for you without ever calling new.
A typical use case might be something like this:
public class Foo {
private final TaskExecutor executor;
#Inject
public Foo(TaskExecutor executor) {
this.executor = executor;
}
}
This works because the instances of Foo are themselves injected, all the way up the Object Graph. See: Getting started
With dependency injection, objects accept dependencies in their constructors. To construct an object, you first build its dependencies. But to build each dependency, you need its dependencies, and so on. So when you build an object, you really need to build an object graph.
Building object graphs by hand is labour intensive, error prone, and makes testing difficult. Instead, Guice can build the object graph for you. But first, Guice needs to be configured to build the graph exactly as you want it.
So, typically, you don't create a Singleton pattern and put the injector into it, because you should rarely call Guice.createInstance outside of your main class; let the injector do all the work for you.
All that being said, to solve the problem you're actually asking about, you want to use Jukito.
The combined power of JUnit, Guice and Mockito. Plus it sounds like a cool martial art.
Let's go back to the use case I've described above. In Jukito, you would write FooTest like this:
#RunWith(JukitoRunner.class)
public class FooTest {
public static class Module extends JukitoModule {
#Override
protected void configureTest() {
bindMock(TaskExecutor.class).in(TestSingleton.class);
}
}
#Test
public void testSomething(Foo foo, TaskExecutor executor) {
foo.doSomething();
verify(executor, times(2)).someMethod(eq("Hello World"));
}
}
This will verify that your Mock object, generated by Mockito via Jukito has had the method someMethod called on it exactly two times with the String "Hello World" both times.
This is why you don't want to be generating objects with ObjectFactory in the way you describe; Jukito creates the Injector for you in its unit tests, and it would be very difficult to inject a Mock instead and you'd have to write a lot of boilerplate.