What is the best way to use Guice and JMock?

I started using Guice to do dependency injection in the project, primarily because I need to embed the mocks (using JMock currently) layer from unit test, which makes manual injection very inconvenient.

My question is, what is the best approach for introducing a layout? I currently have a new module in unit test that satisfies the dependencies and binds them to a provider that looks like this:

public class JMockProvider<T> implements Provider<T> { private T mock; public JMockProvider(T mock) { this.mock = mock; } public T get() { return mock; } } 

Passing the layout in the constructor, so the JMock setup might look like this:

  final CommunicationQueue queue = context.mock(CommunicationQueue.class); final TransactionRollBack trans = context.mock(TransactionRollBack.class); Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(CommunicationQueue.class).toProvider(new JMockProvider<QuickBooksCommunicationQueue>(queue)); bind(TransactionRollBack.class).toProvider(new JMockProvider<TransactionRollBack>(trans)); } }); context.checking(new Expectations() {{ oneOf(queue).retrieve(with(any(int.class))); will(returnValue(null)); never(trans); }}); injector.getInstance(RunResponse.class).processResponseImpl(-1); 

Is there a better way? I know that AtUnit is trying to solve this problem, although I miss how it automatically introduces a layout created locally, as mentioned above, but I am looking for either a convincing reason why AtUnit is the correct answer here (other than its ability to change DI and bullying framework without changing the tests), or if there is a better solution for this manually.

+7
java guice jmock
source share
4 answers

You do not need to introduce bullying into the DI framework. I use Guice and JMock quite successfully, and my unit tests do not refer to anything related to Guice. I use only mocks and pass null where applicable.

DI will allow you to inject and construct the dependencies of the current class, so if you want to add a class that mocked the class (which actually stops the dependency graph), you just need to pass it on. Misko Hevery stated in one of Google Tech Talks that unit tests should be dotted with new and null because their scope is localized to the individual unit test method - I have to agree with it.

Is there any need to use Guice in tests, that is, if they are not functional / integration tests?

Will the test work if it excludes the injector? Could you reorganize your test for something like:

 final CommunicationQueue queue = context.mock(CommunicationQueue.class); final TransactionRollBack trans = context.mock(TransactionRollBack.class); context.checking(new Expectations() {{ oneOf(queue).retrieve(with(any(int.class))); will(returnValue(null)); never(trans); }}); RunResponse r = new RunResponse(queue, trans); // depending on the order r.processResponseImpl(-1); 
+12
source share

From what you said, it sounds like you are not performing a real unit test. When performing a unit test for a class, you focus on only one class. When you run your unit test, execution should only run the test class and avoid running methods from related classes.

JMock / Easymock are tools that help you achieve unit testing of your class. They are not useful in the integration test.

In the context of unit testing, Guice overlaps with JMock / Easymock. Guice forces users to pollute their code with all kinds of annotations (e.g. @Inject) to achieve the same result as JMock / Easymock. I really strongly disagree with Ghys on how they help in testing. If developers have to use Guice instead of JMock / Easymock, they either do not perform the real unit test properly or try to check the controller classes.

The test controller class should not be run at the unit level, but at the integration test level. For an integration test, using Jakarta Cactus is very useful. In an integration test, developers should have all the dependencies and therefore there is no need to use Guice.

As a conclusion, I see no reason to use Guice when testing the product. Google Guice may be useful in different contexts, but testing.

+1
source share

Yishai, I have to fix the fact that the institution of the best design should be credited to the dependency dependency pattern introduced by Martin Fowler. Guice is a tool to help you if your codes are already followed. Guice contributes nothing to your better coding. Guice solves DI ad-hoc (at the annotation level), so it cannot be considered used as the basis of DI. This is the big difference between Spring's xml-based DI container and Guice's annotation-based DI container.

I took some time to read your code published at the beginning (I usually do not) to understand why you told unit test that your class is not possible. I finally understand the problem you are facing. From what I see at the unit test level, you tried to simulate the flow of part of the code when it runs inside the Java EE server. This is the reason you are stuck. I do not know what incentive is here, but I am afraid that your efforts to prepare all these environmental dependencies will be wasted :(

Writing a unit test is a test of the "business logic" that is independent of the technology used. Perhaps there is another requirement that this business logic must run in a quality of service (QoS) environment. This requirement is a “technical requirement”. In your example, CommunicationQueue and TransactionRollBack basically function to meet "technical requirements." The situation is that your "business requirement" is surrounded by all these environmental units. What you need to do is refactor your code so that your “business requirement” is separated from methods that have no dependencies. Then you write unit-test for these methods.

I still believe that you are doing functional testing. Performing functional tests at the unit test level is very time-consuming, and you should not do this. I hope this helps

0
source share

Yishai, it looks like you need AOP to get around these dependencies. AspectJ and AspectWerkz are both useful resources. However, AspectWekz has a very nice feature of weaving aspect classes at runtime using JVM hotswap technology. Of course, these engineering efforts should only be applied at the testing level.

I put a lot of effort into resolving dependencies while doing unit testing. Tools such as JMock, EasyMock, Java EE micro-container, AspectJ, AspectWerkz, Spring IoC can be used to solve the DI problem. None of these tools force developers to place testing in their production codes. Too bad that Guice violates the concept of keeping your codes from any kind of testing. And I do not think this is a tool that will be used in my unit test.

I hope I gave you enough reason to accept the @Inject annotation from your production code.

0
source share

All Articles